$ q.all(p1,p2).then()似乎在两个promises被解决之前触发

时间:2014-01-14 01:51:48

标签: javascript angularjs promise

$资源承诺是否应该与$ q兼容?也许我错了。我有两个$ resource对象,我可能会加载:

$rootScope.foos = Res1.query();    // [ foo1, foo2...]
$rootScope.bars = Res2.query();    // [ bar1, bar2...]

当两个(并且只有两个)查询到达时,我需要广播一个事件。所以我正在使用$ q.all这样:

$q.all([$rootScope.foos.$promise, $rootScope.bars.$promise])
.then(function(){
    // sometimes $rootScope.bars == []
    $rootScope.$broadcast('foos_and_bars!');
});

事件监听器发现$ rootScope.bars为空/ [](一秒后它有数据)


响应@Daiwei 和@ExpertSystem

进行更新

好的,这是JSFiddle: Reproducing JSFiddle

控制台显示在解决promise之前返回$ q.all()。我想要么它被错误使用,或者它是一个与[$ resource,$ scope,$ http等]中的任何一个有关的角色错误......

3 个答案:

答案 0 :(得分:2)

更新

原来是版本冲突问题。 下面提供的解决方案是使用更高版本(使用1.2.8测试),但完全是多余的 有关详细信息,请参阅 Purrell's answer


$resource

上引用文档
  

重要的是要意识到调用$ resource对象方法会立即返回一个空引用(取决于isArray的对象或数组)。从服务器返回数据后,将使用实际数据填充现有引用。这是一个有用的技巧,因为通常将资源分配给模型,然后由视图呈现。具有空对象导致无渲染,一旦数据从服务器到达,则对象用数据填充,并且视图自动重新呈现其自身显示新数据。这意味着在大多数情况下,永远不必为动作方法编写回调函数   [...]
  资源实例和集合具有以下附加属性:

     
      
  • $ promise:...
  •   
  • $已解决:......
  •   

您的Res1Res2是$ resource 对象(不是实例)和(根据文档)调用{{1} } method “立即返回一个空引用”(在你的情况下是一个数组)。 ( UPD :但返回的数组仍然具有其他属性。)

正如文档建议的那样,大多数情况下,您只是将这些空引用分配给Scope并忘记它们(一旦获取数据,模型(以及随后的视图)将自动更新)。


然而,如果您确实有理由希望在数据出现后立即获得明确通知,您可以使用两个“真正的”承诺:

query()

另请参阅此 working example


<强>更新

由于返回的数组也具有// 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

<强> Working demo

答案 1 :(得分:1)

这结果是ngResource和angular之间的意外版本冲突。 Angular是1.2.6,但ngResource是1.2.3。

最初发布的小提琴不适用于类似但不同的ngResource版本问题,即它使用的是一个旧的ngResource版本,它没有用来公开$ promise对象(虽然它们仍在引擎盖下使用)。在ngResource的更高版本中,承诺被公开,因此它们可以用于这样的事情。

@ ExpertSystem的建议很好,但不会解决问题。我之前尝试使用$ q.defer()promises,当出现版本冲突时它也有同样的问题。 在没有版本冲突的情况下工作,但是这是不必要的,当它们已经为您提供方便时,不需要创建自己的承诺。

这是working JSFiddleangular 1.2.1,但对于ngResource来说已经足够了)

答案 2 :(得分:0)

你的$ q.all()之后...你可以使用.spread(函数(prom1,prom2){}代替所有promises返回时运行。按照你现在的方式执行它.then会触发每当数组中的一个项返回时,为什么有时候数组中的一个项是空的。