没有与 AngularJS 直接对应的东西$injector.invoke
在 Angular 中,因为可注入函数预计是useFactory
在设计时定义的提供者。
AngularJS 中只有一个注入器实例,但 Angular 中有一个注入器层次结构,这也使事情变得复杂,因为调用函数的注入器应该存在依赖关系。
处理这个问题的惯用方法是定义所有期望作为提供者调用的函数。这意味着函数仅限于使用定义在其上的注入器(根或子模块)中的实例:
export function fooDefaultStateFactory(baz) {
return () => baz.getStateName();
}
@NgModule({
providers: [
Baz,
{
provider: fooDefaultStateFactory,
useFactory: fooDefaultStateFactory,
deps: [Baz]
}
],
...
})
...
// relative state name
default: '.child',
...
// function with DI injectables
default: fooDefaultStateFactory
然后可以从注入器中检索工厂函数作为任何其他依赖项并调用:
transition => {
...
if (typeof to.default === 'string') {
...
} else if (to.default) {
const defaultState = injector.get(to.default);
if (typeof defaultState === 'function') {
// possibly returns a promise
Promise.resolve(defaultState()).then(...)
} else { ... }
}
}
对应于$injector.invoke
与任何函数一起使用应该大致类似于构造函数定义在 Angular 2/4 中的工作方式Class helper https://github.com/angular/angular/blob/4.4.6/packages/core/src/util/decorators.ts#L99-L142(在 Angular 5 中已弃用)。不同之处在于Class
接受用数组或注释注释的构造函数parameters
静态属性,注释应该是数组的数组,因为依赖项可能涉及装饰器(Inject
, Optional
, etc).
由于装饰器不适用于未注册为提供者的函数,因此该数组应该是普通的,类似于AngularJS 隐式注释 https://docs.angularjs.org/guide/di#implicit-annotation or deps
在角度useFactory
提供者:
function invoke(injector, fnOrArr) {
if (Array.isArray(fnOrArr)) {
const annotations = [...fnOrArr];
const fn = annotations.pop();
const deps = annotations.map(annotation => injector.get(annotation));
return fn(...deps);
} else {
return fnOrArr();
}
}
可以绑定到注入器实例:
const injectorInvoke = invoke.bind(injector);
injectorInvoke([Foo, Bar, (foo: Foo, bar: Bar) => {...}]);
调用函数的代码片段修改为:
...
if (typeof defaultState === 'function' || Array.isArray(defaultState)) {
// possibly returns a promise
Promise.resolve(injectorInvoke(defaultState)).then(...)
} else { ... }
...