在 typescript 中,如果你不小心建立了类似以下两个文件,那么则会发生一个依赖警告。在个别的时候,还可能导致 build 失败的情况。
import Foo from "foo"; export class Bar { private foo: Foo; barFun() { this.foo.xxx(this); } }
import Bar from "bar"; export class Foo { xxx(bar: Bar) { console.log("xxx"); } }
此时由于 bar 中 import 了 foo, 然后 foo 又 import 了 bar,所以产生了 cycle.
bar -> foo -> bar -> foo -> bar -> …
此时我们则可引入 interface
来解决这个循环的依赖.
引入 interface
export interface BarInterface { barFun(): void; }
import Foo from "foo"; export class Bar { private foo: Foo; barFun() { this.foo.xxx(this); } }
import BarInterface from "bar-interface"; export class Foo { xxx(bar: BarInterface) { console.log("xxx"); } }
此时,在进行引入时,则不会发生 clcle 了:
- 引入 BarInterface: bar.interface -> end
- 引入 Bar: bar -> foo -> bar.interface -> end
- 引入 Foo: foo -> bar.interface -> end
适用场景
该方法适用于以下场景:我们需要对历史的项目进行维护,但这个项目拥有多个版本,所以我们需要减少对原代码的入侵量。同时呢,我们在维护的过程中,还需要调用原代码中的相应功能。重要的是,还不能造成 cycle。
比如:
export class FooService { fun1() { } fun2() { } }
现在我们需要对 fun1() 进行功能上的补充,在补充其功能时,还需要调用 fun2(),则建立了以下两个文件:
import FooService from 'foo.service'; import FooFixService from 'foo-fix.service'; export class FooSerivceHook { private fooFixService = new FooFixService(); fun2(fooService: FooService) { this.fooFixService.foo(fooService); } }
import FooService from 'foo.service'; export class FooFixService { foo(fooService: FooService) { // 一些功能性的代码补充,并在补充过程中调用了原来的 fun2()方法 this.fooService.fun2(); } }
最后我们改写原代码:
import FooSerivceHook from 'foo-service.hook'; export class FooService { private fooSerivceHook = new FooSerivceHook(); fun1() { } fun2() { this.fooServiceHook.fun2(); } }
上述代码功能上没有问题,但却引发了 cycle 的问题:
FooService -> FooSerivceHook – > FooService -> …
此时我们则可以使用本文的方法建立 interface 来规避 cycle 的产生,同时由于在原 FooService 上声明了接口实现,在进行其它版本的代码修正的快速迁移代码的过程中,也可以快速的发现迁移过程中的问题。