当服务中存在嵌套的承诺关系时,AngularJS的行为很奇怪
AngularJS behaving strangely when there's a nested relationship of promises in services
我有 2 个 plunkr 准备好来演示我对什么感到困惑。我正在寻求一个明确的解释,确切地解释为什么第一个 plunkr 失败了,但第二个有效。
在第一个 plunkr 中,我模拟调用外部库以执行某种网络身份验证。问题是,当原始控制器级别方法的链中有 2 个承诺时,传递给第一个承诺以在解析时执行的函数永远不会触发,尽管解析了每个承诺,但链上的任何其他承诺也不会触发。
http://plnkr.co/edit/6uKnVvEI3bJvfmaUoWN0
但是,当我将调用更改为使用 $timeout 时,无论它是用于模拟延迟,还是仅用于包装从实际外部操作(如调用 REST API)返回的 deferred.resolve ,一切都按预期工作。在第二个 plunkr 中,您可以看到一旦两个 deferred.resolve 调用都被修改为包装在$timeout调用中,登录功能就可以正常工作。
此外,我还包括了一个其他人建议的测试用例,作为在返回承诺之前解决承诺会失败的问题。这显然不是这种情况,因为第二个 plunkr 在这样做时工作得很好。请注意,此替代方法不使用$timeout但仍然可以正常工作。这向我表明,当两个服务(testApi,authService)之间的关系有一些特殊之处时,当两者都返回承诺对象时,导致必须向上解析的嵌套承诺链。
http://plnkr.co/edit/xp8NeZKWDep6cPys5gJu?p=preview
有谁能向我解释为什么这些承诺在一种情况下失败,但在另一种情况下,当它们没有嵌套或嵌套包装在$timeout中时起作用?
我的预感与摘要周期有关,但就我的生命而言,我不明白为什么摘要周期会影响基本上独立于控制器运行的服务。它们不是需要在控制器加载之前解析的$scope上的属性,而是包装返回承诺的服务调用的函数。
你的预感是对的。当你使用setTimeout
时,它会触发一个Angular一无所知的事件;如果您改用$timeout
,情况并非如此。因此,要使第一个 Plunker 脚本正常工作,您需要通过调用 $rootScope.$apply()
手动启动摘要循环:
angular.module('testApi', []).factory('testApi', function($q, $rootScope) {
...
setTimeout(function() {
$rootScope.$apply(function() {
deferred.resolve({user: { id: '1', name: 'bozo'}});
});
}, 1000);
在这里普朗克。
如果您坚持使用$timeout
,则不需要执行上述任何操作,我建议您这样做。
这个 SO 问题提供了更多关于为什么承诺回调仅在进入$digest周期时才调用的信息。
- AngularJs-在两个数组中查找关系信息
- 使用AngularJS在Firebase中显示关系数据
- AngularJS中REST资源的链接(关系)
- 如何在AngularJS中将依赖关系传递给原型函数
- 如何使 AngularJS 指令在不隔离作用域的情况下清楚地定义其依赖关系
- 同一数组(AngularJS)中的javascript对象之间的一对一关系
- AngularJS 控制器注入依赖关系 - 为什么构造函数有 []
- 在 angularjs 中声明多个服务依赖关系
- 当服务中存在嵌套的承诺关系时,AngularJS的行为很奇怪
- Angularjs-在尝试使用全局服务时无法解决所需的依赖关系
- AngularJS中的$resource关系
- AngularJS:依赖关系管理
- 如何在AngularJs中设置来自其提供商的服务的依赖关系
- 具有表之间关系的AngularJS资源
- 我应该如何管理AngularJS中的依赖关系
- AngularJS中拉拉威尔雄辩的关系
- AngularJS——一个更简单的绑定一对一和一对多关系的方法
- angularJS中标题和正文部分具有不同依赖关系的单独模块
- AngularJS的简单骨架,没有依赖关系
- 在AngularJS中管理模型关系