Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/417.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript $q.all(p1,p2).then()似乎在两个承诺都得到解决之前触发_Javascript_Angularjs_Promise - Fatal编程技术网

Javascript $q.all(p1,p2).then()似乎在两个承诺都得到解决之前触发

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

$resource承诺是否应该与$q兼容?也许我用错了。我有两个$resource对象,可以像这样加载:

$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”。这让我误解了文件。我现在又试了一次,效果如你所说。多么阴暗的阴谋啊:)