关于这两个很大的来源:NZakas - Returning Promises in Promise Chains和MDN Promises,我想问一下:
每次我们从promise履行处理程序返回一个值时,该值是如何传递给从同一个处理程序返回的新promise?
例如,
let p1 = new Promise(function(resolve, reject) {
resolve(42);
});
let p2 = new Promise(function(resolve, reject) {
resolve(43);
});
let p3 = p1.then(function(value) {
// first fulfillment handler
console.log(value); // 42
return p2;
});
p3.then(function(value) {
// second fulfillment handler
console.log(value); // 43
});
在此示例中, p2
是一个承诺 . p3
也是来自 p1
履行处理程序的承诺 . 但是 p2 !== p3
. 相反 p2
以某种方式神奇地解析为 43
(如何?)然后将该值传递给 p3
的履行处理程序 . 即使是这里的句子也令人困惑 .
你能否向我解释一下究竟发生了什么?我对这个概念感到困惑 .
4 回答
假设抛出
then()
回调函数拒绝结果承诺失败,并且从then()
回调返回以成功值实现结果承诺 .但有时,即使在延续期内,我们也不知道我们是否成功 . 我们需要更多时间 .
但是,如果我在那里进行异步工作,那么
return
或throw
就太晚了,不是吗?这就是为什么如果你不能 resolve to another Promise ,Promises就没用了 .
这并不意味着在你的例子中
p2
会变成p3
. 它们是单独的Promise对象 . 但是,通过从产生p3
的then()
返回p2
,您说 “I want p3 to resolve to whatever p2 resolves, whether it succeeds or fails”.至于如何发生这种情况,它是特定于实现的 . 在内部,您可以将
then()
视为创建新的Promise . 实施将能够随时满足或拒绝它 . 通常情况下,当您返回时,它会自动完成或拒绝它:同样,这是非常伪代码,但显示了如何在Promise实现中实现
then()
的想法 .如果我们想要添加对Promise的解析支持,我们只需要修改代码以便在传递给
then()
的callback
返回Promise时有一个特殊的分支:让我再次澄清,这不是一个真正的Promise实现,并且有很大的漏洞和不兼容性 . 但是,它应该让您直观地了解Promise库如何实现解析Promise . 在您对这个想法感到满意之后,我建议您先看看实际的Promise实现方式handle this .
基本上
p3
是return
- 另一个承诺:p2
. 这意味着p2
的结果将作为参数传递给下一个then
回调,在这种情况下它会解析为43
.每当您使用关键字
return
时,您都会将结果作为参数传递给下一个then
的回调 .你的代码:
等于:
顺便说一下,我注意到你使用的是ES6语法,你可以通过使用胖箭头语法来获得更轻的语法:
一个简化版本如何工作(只有伪代码)
整个事情要复杂得多,因为你必须要小心,承诺已经解决了,还有更多的东西 .
我将尝试回答“为什么
then
回调可以返回Promise
s”这个问题更具规范性 . 为了采取不同的角度,我将Promise
与较不复杂和容易混淆的容器类型进行比较 -Array
s .Promise
是未来值的容器 .Array
是任意数量值的容器 .我们不能将常规函数应用于容器类型:
我们需要一种机制将它们提升到特定容器的上下文中:
但是当提供的函数本身返回相同类型的容器时会发生什么?
sqra
表现得像预期的那样 . 它只返回一个具有正确值的嵌套容器 . 这显然不是很有用 .但是如何解释
sqrp
的结果呢?如果我们遵循自己的逻辑,它必须像Promise {[[PromiseValue]]: Promise {[[PromiseValue]]: 9}}
- 但事实并非如此 . 那么这里有什么魔力呢?为了重建机制,我们只需要稍微调整一下我们的
map
方法:flatten
只需要一个函数和一个值,适用函数的值和解包结果,因此它将嵌套的数组结构减少一个级别 .简单地说,
then
在Promise
的上下文中等同于map
与Array
的上下文中的flatten
相结合 . 这种行为非常重要 . We can apply not only normal functions to a Promise but also functions that itself return a Promise.实际上,这是函数式编程的领域 .
Promise
是 monad 的具体实现,then
是bind
/chain
,返回Promise
的函数是monadic函数 . 当您了解Promise
API时,您基本上了解所有monad .