关于 Promise 解析
你在这里目睹的事情叫做递归的then
能够分辨率。 Promises/A+规范中的promise解析过程包含以下子句:
onFulfilled或onRejected返回值x,运行Promise解析过程 [[Resolve]](promise2, x)
ES6 Promise 规范(Promise 解包)包含类似的条款。
这要求当resolve
操作发生:或者在 Promise 构造函数中,通过调用Promise.resolve
或者在你的情况下then
链式承诺实施must如果返回值是一个承诺,则递归地解开返回值。
在实践中
这意味着如果onFulfilled
(the then
)返回一个值,尝试自己“解析”承诺值,从而递归地等待整个链。
这意味着以下内容:
promiseReturning().then(function(){
alert(1);
return foo(); // foo returns a promise
}).then(function(){
alert(2); // will only run after the ENTIRE chain of `foo` resolved
// if foo OR ANY PART OF THE CHAIN rejects and it is not handled this
// will not run
});
例如:
promiseReturning().then(function(){
alert(1);
return Promise.resolve().then(function(){ throw Error(); });
}).then(function(){
alert("This will never run");
});
然后:
promiseReturning().then(function(){
alert(1);
return Promise.resolve().then(function(){ return delay(2000); });
}).then(function(){
alert("This will only run after 2000 ms");
});
这是不是一个好主意?
这是承诺规范过程中备受争议的话题,讨论了第二个不表现出这种行为的链方法,但决定反对(在 Chrome 中仍然可用,但很快就会被删除)。您可以阅读整个辩论的内容在此讨论主题中 https://esdiscuss.org/topic/promise-cast-and-promise-resolve. 这种行为是出于务实的原因这样您就不必手动执行此操作。
在其他语言中
值得一提的是,其他语言并没有这样做,Scala 中的 future 或 C# 中的任务都没有这个属性。例如在 C# 中你必须调用Task.Unwrap
任务以等待其链解决。