Javascript $q.all(p1,p2).then()似乎在两个承诺都得到解决之前触发
$resource承诺是否应该与$q兼容?也许我用错了。我有两个$resource对象,可以像这样加载:Javascript $q.all(p1,p2).then()似乎在两个承诺都得到解决之前触发,javascript,angularjs,promise,Javascript,Angularjs,Promise,$resource承诺是否应该与$q兼容?也许我用错了。我有两个$resource对象,可以像这样加载: $rootScope.foos = Res1.query(); // [ foo1, foo2...] $rootScope.bars = Res2.query(); // [ bar1, bar2...] 当两个(并且只有两个)查询都到达时,我需要广播一个事件。所以我使用$q。都是这样的: $q.all([$rootScope.foos.$promise, $rootScop
$rootScope.foos = Res1.query(); // [ foo1, foo2...]
$rootScope.bars = Res2.query(); // [ bar1, bar2...]
当两个(并且只有两个)查询都到达时,我需要广播一个事件。所以我使用$q。都是这样的:
$q.all([$rootScope.foos.$promise, $rootScope.bars.$promise])
.then(function(){
// sometimes $rootScope.bars == []
$rootScope.$broadcast('foos_and_bars!');
});
事件侦听器发现$rootScope.bar为空/[]
(当一秒钟后它有数据时)
更新以响应@Daiwei和@ExpertSystem 好的,下面是关于这个的JSFIDLE: 控制台显示在解析承诺之前返回$q.all()。我想要么它被错误地使用了,要么它是一个角度错误,与[$resource、$scope、$http等]中的任何一个有关,在$q.all()之后,…您可以使用.spread(function(prom1,prom2){}而是在所有承诺返回后运行。按照您当前的操作方式。然后将在数组中的每一项返回时激发。因此,有时数组中的一项为空。更新: 这是一个版本冲突问题。 下面提供的解决方案适用于更高版本(使用1.2.8测试),但完全是多余的。
有关更多信息,请参见
引用上的文档: 重要的是要认识到调用$resource对象方法会立即返回空引用(对象或数组取决于isArray)。从服务器返回数据后,现有引用将填充实际数据。这是一个有用的技巧,因为通常将资源分配给模型,然后由视图进行渲染。如果对象为空,则不会进行渲染,一旦数据从服务器到达,则对象将填充数据,并且视图自动重新呈现自身,显示新数据。这意味着在大多数情况下,不必为操作方法编写回调函数。
[…]
资源实例和集合具有以下附加属性:
- $承诺:
- $已解决:
Res1
和Res2
是$resource对象(不是实例),并且(根据文档)调用query()
方法“立即返回空引用”(在您的例子中是数组)。(UPD:返回的数组仍然具有附加属性。)
正如文档所建议的,大多数情况下,您只是将这些空引用分配给范围,而忽略它们(一旦获取数据,模型(以及随后的视图)将自动更新)
然而,如果你确实有理由希望在数据一到就得到明确的通知,你可以使用两个“真正的”承诺:
// Create two deferred objects
var deferred1 = $q.defer();
var deferred2 = $q.defer();
// As soon as the data arrives, resolve the deferred objects
$rootScope.foos = Res1.query(function () { deferred1.resolve(); });
$rootScope.bars = Res2.query(function () { deferred2.resolve(); });
// Combine their promises using `$q.all()`
$q.all([deferred1.promise, deferred2.promise]).then(...);
另请参见此
更新 由于返回的数组还具有
$promise
属性,因此更简洁的版本是:
$rootScope.foos = Res1.query();
$rootScope.bars = Res2.query();
$q.all([$rootScope.foos.$promise, $rootScope.bars.$promise]).then(...);
这是ngResource和angular之间的意外版本冲突。angular在1.2.6上,但ngResource在1.2.3上 最初发布的fiddle没有解决类似但不同的ngResource版本问题,即它使用的是一个旧的ngResource版本,该版本没有用于公开$promise对象(尽管它们仍然在后台使用).在ngResource的更高版本中,承诺被公开,因此它们可以用于类似的事情 @ExpertSystem的建议很好,但不会解决这个问题承诺优先,当存在版本冲突时,它也有相同的问题。在没有版本冲突的情况下它确实有效,但也没有必要,因为为了方便起见,不需要创建自己的承诺
以下是(在
angular 1.2.1
中,但这对于ngResource来说已经足够好了)您可以在Res1.query()中发布相关代码吗
?这应该很好。你能准备一把小提琴或重现问题吗?@ExpertSysterm好了,我们开始了,重现得很好:文档中$q似乎没有.spread函数。你是指不同的promise实现吗?是的。我的错,我还发现了其他使用spread函数的实现输入很好,但我要注意1)引用不仅仅是一个空数组。它有$promise和$resolved属性(供您使用)。你链接的页面上提到过。搜索“资源实例和集合具有这些附加属性”。2) 使用$resource公开的$promise对象是可以的,这就是它们的用途。3) 这些$promise道具是“真正的”promise,最终通过$q创建。所以结果是版本冲突!更多的笔记在我的答案空间下面。我真的很感谢你在这里花时间思考,非常感谢。真奇怪。我(以为我已经)尝试了最新版本,在未定义的地方,$promise
和“$resolved”。这让我误解了文件。我现在又试了一次,效果如你所说。多么阴暗的阴谋啊:)