Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 调用具有角度依赖项的函数_Angular_Typescript_Configuration_Routing_Angular5 - Fatal编程技术网

Angular 调用具有角度依赖项的函数

Angular 调用具有角度依赖项的函数,angular,typescript,configuration,routing,angular5,Angular,Typescript,Configuration,Routing,Angular5,使用Angular 5和UIRouter状态路由。根据此接口,我正在使用一个附加的自定义路由状态属性 interface AugmentedNg2RouteDefinition extends Ng2StateDeclaration { default?: string | ((...args: any[]) => string | Promise<string>); } 要使默认值真正起作用,我必须配置路由转换服务: @NgModule({ imports: [

使用Angular 5和UIRouter状态路由。根据此接口,我正在使用一个附加的自定义路由状态属性

interface AugmentedNg2RouteDefinition extends Ng2StateDeclaration {
    default?: string | ((...args: any[]) => string | Promise<string>);
}
要使
默认值真正起作用,我必须配置路由转换服务:

@NgModule({
  imports: [
    ...
    UIRouterModule.forChild({  // or "forRoot"
      states: ...
      // THIS SHOULD PROCESS "default" PROPERTY ON ABSTRACT STATES
      config: (uiRouter: UIRouter, injector: Injector, module: StatesModule) => {
        uiRouter.transitionService.onBefore(
          // ONLY RUN THIS ON ABSTRACTS WITH "default" SET
          {
            to: state => state.abstract === true && !!state.self.default
          },
          // PROCESS "default" VALUE
          transition => {
            let to: transition.to();
            if (angular.isFunction(to.default)) {
              // OK WE HAVE TO EXECUTE THE FUNCTION WITH INJECTABLES SOMEHOW
            } else {
              // this one's simple as "default" is a string
              if (to.default[0] === '.') {
                  to.default = to.name + to.default;
              }
              return transition.router.stateService.target(to.default);
            }
          }
        );
      }
    })
  ]
})
export class SomeFeatureModule { }
因此,当函数可能具有一些可注入的服务/值时,问题是调用
默认值

配置函数的injector(
config:(uiRouter:uiRouter,injector:injector,module:StatesModule)
)只能用于获取服务实例,但不能使用可注入参数调用函数

在AngularJS中,这将通过调用函数并注入其参数的
$injector.invoke(…)
来实现

主要问题
当它被定义为带有可注入项的函数时,我应该如何处理
default

这是通过添加关于解析服务的部分来解决这个问题的一种方法

// THE IMPORTANT PART
config: (uiRouter: UIRouter, injector: Injector, module: StatesModule) => {
   uiRouter.transitionService.onBefore(
      // HookMatchCriteria
      {
         to: state => state.abstract === true && !!state.self.default
      },
      // TransitionHookFn
      transition => {
         let to: transition.to();
         if (typeof to.default === "string") {
            return transition.router.stateService.target(to.default);
         } else if (typeof to.default === "function") {
            let functionPromise = Promise.resolve(to.default(injector));
            return functionPromise.then((toDefault) => transition.router.stateService.target(toDefault));
         }
}
检查默认值是否为
string
的第一部分很明显。 在第二个
if
中,我检查参数是否是函数,这会自动将其视为TypeScript中的函数,以便可以直接调用。对于可以是
Promise
string
的结果,我使用该方法。这个方法为两个输入返回一个新的
Promise
,这样我们就可以通过调用stateService来链接它,它将返回一个
Promise
,这是TransitionHookFn的有效返回

要解析服务,您可以按如下方式更改接口:

interface AugmentedNg2RouteDefinition extends Ng2StateDeclaration {
    default?: string | ((injector: Injector, ...args: any[]) => string | Promise<string>);
}
// relative state name
default: '.child',
// absolute state name
default: 'parent.child',
// function with DI injectables
default: (injector: Injector) => {
    let auth: AuthService = injector.get(AuthService);
    let stateService: StateService = injector.get(StateService);
    if (auth.isAuthenticated) {
        return '.child';
    } else {
        return stateService.target('.login', { ... });
    }
}
// function with DI injectables returning a promise
default: (injector: Injector) => {
    let items: ItemsService = injector.get(ItemsService);
    return items
        .getTotal()
        .then((count) => {
            return count > 7
                ? '.simple'
                : '.paged';
        });

AngularJS
$injector.invoke在AngularJS中没有直接的对应项,因为可注入函数应该是在设计时定义的
useFactory
提供程序

AngularJS中只有一个注入器实例,但AngularJS中有一个注入器层次结构,这也使事情变得复杂,因为调用函数的注入器上应该存在依赖关系

处理这个问题的惯用方法是定义所有预期作为提供程序调用的函数。这意味着一个函数被限制使用它在上定义的注入器的实例(根模块或子模块):

然后,工厂功能可以作为任何其他依赖项从喷油器中检索并调用:

  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中构造函数定义的工作方式(Angular 5中不推荐使用)。区别在于
接受使用数组或
参数
静态属性进行注释的构造函数,注释应为数组数组,因为依赖项可能涉及修饰符(
注入
可选
,等等)

由于装饰器不适用于未注册为提供程序的函数,因此该数组应为普通数组,类似于Angular
useFactory
provider中的或
deps

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 { ... }
  ...

问题是
default
可以在某个点上起作用,但事实上它不是。它到底是什么样子的?配置函数的注入器只能得到我在这里不能真正使用的注入器实例-这意味着什么?这些实例是什么?预期会出现哪些实例?这里需要清楚的问题陈述。@estus:
默认值
可以是字符串,也可以是返回字符串或字符串承诺的函数。问题是此函数可能需要angular的DI容器提供的参数。这就是为什么要在AngularJS中使用
$injector.invoke
,但是
.invoke
函数在我的Angular 5代码上下文中不可用。您现在了解问题了吗?Angular中没有$injector.invoke,启用DI的函数应该定义为提供程序。这个函数和这些参数(服务?)是什么真的很重要。你的评论没有解释这一点,配置函数的注入器只能得到我在这里不能真正使用的注入器实例。请用详细解释您案例的示例更新问题,因为这个问题无法在一般情况下解决。@estus我知道没有
$injector.invoke
。你觉得我为什么一开始就问这个问题?我显然没有正确地描述我的问题,因为您不了解
default
state属性的作用。因此,注入参数(当
default
是一个具有注入参数的函数时)可以是任何提供信息以决定应选择哪个默认子状态的内容。i、 一些认证服务。。。我的问题对于那些认真阅读的人来说已经足够详细了。这不是什么基本问题。这是一个进步的问题。@estus:我希望我经过严格编辑的问题现在更清楚、更容易理解。这也可能是因为我缺少一些知识,所以我不能把我的问题说得更清楚。似乎我遗漏了什么。您使用了一个简单的
default
函数。无参数。。。但这并不是我想要解决的问题。至少不是我正在挣扎的例子。。。假设
default
函数有一个服务参数:
default:(myService:myService)=>{…}
。您现在将如何调用该函数?您必须以某种方式获得可注入服务实例。在AngularJS中,只需调用
$injector.invoke()
,然后从DI容器中注入参数,但在Angular5中,我们没有
invoke
函数……好的,我知道现在我读得不够仔细,所以我没有理解这是主要问题。然后,我会更改函数定义,将
注入器
作为参数,然后解析函数中的服务
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 { ... }
  ...