AngularJS UI 路由器未按顺序执行未指定的解析依赖项

AngularJS UI Router not executing unspecified resolve dependencies in order

我目前 运行 遇到 UI 路由器如何处理它加载其解析的顺序的问题。我想要实现的最终目标是让服务能够加载和存储数据,并且只加载(请求)一次数据,然后通过服务访问这些数据。

我目前实现它的方式遵循以下模式:

在更高级别的状态解析中,告诉服务加载其数据。解析的结果不是子服务的依赖,因为数据是通过在控制器中注入服务来访问的。 子状态解析可能取决于在先前状态中 "primed" 的服务 这在您通常单击应用程序时效果很好(即,状态 a -> 状态 a.b -> 状态 a.b.c)但是,当您直接进入嵌套状态时它会崩溃(状态 a.b 或状态 a.b.c)。出现此问题是因为 UI 如果子状态未将父状态的解析指定为依赖项,路由器将无法确保执行解析的顺序。请参阅以下示例:

app.config(function($stateProvider) {

  $stateProvider
  .state('a', {
    url: "/a",
    resolve: {
      data: function(service) {
        return service.getData(); // makes network request
      }
    }
  })
  .state('a.b', {
    url :"/b",
    resolve: {
      specificData: function(service) { // if you add data as a dependency here, it works fine
        return service.useDataToGetSpecificData(); // doesn't make network request
      }
    }
  })

});

在示例中,如果用户直接进入状态 a.b,特定数据解析将失败。 service.useDataToGetSpecificData 不发出网络请求并访问当前存储在服务中的数据。此调用失败,因为状态 a 的解析尚未完成,因为它是网络请求。

一个解决方案是让服务处理它还没有数据的情况,并通过等待直到它有数据来管理它,但是对于服务将要做什么感觉有点夸大了,而且似乎击败 UI 路由器的要点。

另一个解决方案(我目前正在使用的)是将 "data" 添加为状态 a.b 中解析的依赖项,即使它未被使用。这迫使 a.b 等待 a 完成其解析,并且一切正常。然而,这感觉像是一种 hack,而且非常不直观。任何在不知情的情况下查看此代码的人都会挠头,为什么在 a.b 的解析中声明了这个未使用的变量。

在不指定依赖项的情况下无法保证解析的顺序是 UI 路由器的行为方式,所以我觉得我一定是在做一些奇怪的/错误的事情。

Another solution (what I'm currently going with) is adding "data" to as a dependency of the resolve in state a.b even though it isn't used. This forces a.b to wait on a to finish its resolves, and everything works great. However, this feels like a hack and is extremely non intuitive

这是常见的方法。我通常这样做是为了向一条路线添加多个顺序解析。例如,我经常添加一个 attachUser 挂钩 returns 来自 HTTP GET 请求的承诺,然后添加另一个 isLoggedIn 具有 attachUser 作为依赖项。我搜索了很多,但从未找到更好的。除了 angular 的注入器之外,在 ui-router 中没有为这种情况编写任何特殊内容。即使您的情况因继承而特殊,这与 here and here.

完全相同。

so I feel like I must be doing something weird / wrong.

你不是。这很可能被认为很奇怪/错误

我有一个类似的场景,它对我有用,就像你想要的那样。我的配置如下所示(以您的配置为基础):

app.config(function ($stateProvider) {
   $stateProvider
   .state('root', {
      abstract: true,
      resolve: {
         data: function (service) {
            return service.getData(); // makes network request
         }
      }
   })
   .state('a', {
      url: "/a",
      parent:'root',
      resolve: {
         data: function (data) {
            return data; 
         }
      }
   })
   .state('b', {
      url: "/b",
      parent:'a',
      resolve: {
         specificData: function (service) { 
            return service.useDataToGetSpecificData(); 
         }
      }
   })
});

我的情况的不同之处在于抽象 'root' 状态,无论 url 请求如何,我都需要加载一些全局数据。你能试试这个方法吗?