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 请求如何,我都需要加载一些全局数据。你能试试这个方法吗?
我目前 运行 遇到 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 请求如何,我都需要加载一些全局数据。你能试试这个方法吗?