过去,我曾经使用过jQuery延迟/承诺,但是我试图转向javascript承诺。我有一个功能,需要按顺序进行多个网络调用,然后可以按任何顺序进行多个网络调用,但是所有这些都需要解决,然后再继续进行。我先从顺序调用开始,然后按顺序进行,但随后从第二次调用的结果开始,我需要遍历这些结果,并在随后的调用中生成可变数量(目前为6)。我不在乎这些命令的执行顺序,但是在我继续之前,确实需要等待所有命令解决。我认为这种模式会奏效。但事实并非如此。
function doLotsOfStuff(){
firstNetworkCall()
.then(function(data){
// do stuff with data
return secondNetworkCall();
})
.then(function(data){
// do stuff with data
var promises = data.map(function(item){
// All of these calls (happens to be 6)
// need to be done before I continue
return thirdIndependentCall(item.Info);
});
// at this point I see [Promise, Promise, ....]
// all are unresolved
return Promise.all(promises);
})
.then(function(results){
// executes immediately after the Promises.all() line
// none of them are resolved
// results is just one unresolved promise
});
}
我可以像这样将最后一步链接到Promises.all()
return Promise.all(promises)
.then(function(results){
// this works!
})
但是,如果之后我想链接更多的东西,我必须继续将它们插入。好像我正在丢失一些信息。
编辑
我在简化代码中复制了错别字,而在我的实际代码中却没有。在链中添加.catch()
的建议是一个很好的建议,我尝试了一下。现在它抛出firstNetworkCall(...).then(...).then(...).catch is not a function.
我认为问题在于我的某些代码(仍在某处)仍依赖于jQuery.Deffered
,并且在Promise中不能很好地发挥作用。
很高兴知道我的初始模式应该可以工作-如果我与正在使用的异步处理类型保持一致。
答案 0 :(得分:4)
更改此:
Promises.all(promises)
对此:
Promise.all(promises)
您所拥有的东西将引发异常(因为未定义Promises
捕获的.then()
,然后拒绝了Promise链。
这是经典的原因,为什么在链的末尾始终应该有一个.catch()
,因为如果记录该拒绝,它可能会告诉您错误是什么。
如果要将任何jQuery Promise转换为ES6 Promise,以便可以在任何地方使用.catch()
或仅保证一致的行为,则可以用Promise.resolve()
将它们包装起来,如下所示:
Promise.resolve(firstNetworkCall()).then(...).catch(...)
或者这个:
var promises = data.map(function(item) {
// All of these calls (happens to be 6)
// need to be done before I continue
return Promise.resolve(thirdIndependentCall(item.Info));
});
// at this point I see [Promise, Promise, ....]
// all are unresolved
return Promise.all(promises);
并且请记住,某些较新的jQuery版本比其他版本更兼容ES6 Promise。