Dan*_*aum 34 javascript promise ecmascript-6 es6-promise
当我开始研究Promises时,我的理解已经停止在我未发现的下面的问题上(我发现所有这些都是对Promise构造函数的具体讨论,以及Promise' then'函数 - 但不是一个比较它们的设计模式的讨论).
1. Promise构造函数
从MDN文档中,我们使用了Promise构造函数(添加了我的注释):
new Promise(function(resolve, reject) { ... }); // <-- Call this Stage 1
Run Code Online (Sandbox Code Playgroud)
带有两个参数的函数对象
resolve和reject.第一个参数履行承诺,第二个参数拒绝承诺.一旦我们的操作完成,我们可以调用这些函数.
2. then功能
移动到then功能,可以在一个被称为Promise对象(返回一个新的Promise对象),我们有由文档中描述的以下函数签名(加上我的意见):
p.then(onFulfilled, onRejected);
Run Code Online (Sandbox Code Playgroud)
链接
因为该
then方法返回Promise,所以您可以轻松地链接然后调用.
var p2 = new Promise(function(resolve, reject) {
resolve(1); // <-- Stage 1 again
});
p2.then(function(value) {
console.log(value); // 1
return value + 1; // <-- Call this Stage 2
}).then(function(value) {
console.log(value); // 2
});
Run Code Online (Sandbox Code Playgroud)
我的问题
从上面的代码片段中,我似乎很清楚,传递给resolve阶段1中的函数的值(在第二次出现resolve- 下面的(2),上面)被传递到下一个阶段(后面的第一个then函数)相同的代码片段). 在阶段1中没有返回值. 但是,它是阶段2 的返回值,然后传递到下一阶段(第二个then函数).
在创建a的设计模式Promise与then现有promise(也返回a Promise)上使用函数之间缺乏对应关系,只是一个历史的侥幸(一个需要调用回调但不返回任何内容,另一个返回一个值,但不会调用回调)?
或者我错过了Promise构造函数使用与then函数不同的设计模式的根本原因?
Lar*_*rsH 28
Bergi的答案很棒,对我很有帮助.这个答案是对他的补充.为了可视化Promise()构造函数和then()方法之间的关系,我创建了这个图.我希望它可以帮助某些人......甚至可能是我,几个月之后.
这里的主要思想是传递给Promise()构造函数的"executor"函数设置动作中的任务,这些任务将设置 promise 的状态 ; 而你传递给的处理程序then()将对承诺的状态作出反应.
(代码示例改编自Jake Archibald的经典教程.)
这是对事物如何工作的高度简化的观点,遗漏了许多重要的细节.但我认为如果能够抓住对预期目的的良好概述,它将有助于避免在进入细节时产生混淆.
一个重要的细节是传递给Promise()构造函数的执行函数被立即调用(在构造函数返回promise之前); 而传递给该then()方法的处理函数直到稍后才会被调用(如果有的话).
BERGI提到这一点,但我想再说一遍,而不使用术语A /同步,可如果你不仔细阅读混淆:函数之间的区别调用一些与异步调用异步很容易在通信粉饰.
resolve() 不是 onFulfill()我想强调的是,因为它混淆了我一会儿还有一个细节,就是resolve()和reject()传递给回调Promise()构造函数的执行功能都没有后传递给回调then()方法.回想起来,这似乎是显而易见的,但明显的联系让我在圈子里旋转了太久.肯定有一种联系,但它是一个松散的,动态的.
相反,resolve()和reject()回调函数是由"系统"提供的函数,并Promise在创建promise时由构造函数传递给执行函数.resolve()调用该函数时,将执行系统代码,该代码可能会更改promise的状态,并最终导致onFulfilled()异步调用回调.不要认为呼叫resolve()是一个紧密的包装onFulfill()!
Ber*_*rgi 25
Promise构造函数和then方法之间没有对应关系,因为它们是两个独立的东西,设计用于不同的目的.
该Promise构造仅用于promisifying 1个异步函数.实际上,正如你所说,它是建立在调用 resolve/reject回调上以异步发送值,并且在这种情况下没有返回值.
该Promise构造本身并借此"解析"回调(与它同步传递resolve和reject)实际上是上了年纪的增强递延模式,并承担没有预期相似的then回调.
var p = new Promise(function(res, rej) { | var def = Promise.Deferred();
setTimeout(res, 100); | setTimeout(def.resolve, 100);
}); | var p = def.promise;
Run Code Online (Sandbox Code Playgroud)
then相比之下,回调是经典的异步回调,具有可以从中获得的附加功能return.它们被异步调用以接收值.
p.then(function(val) { … });
Run Code Online (Sandbox Code Playgroud)
总结差异:
Promise是一个构造函数,then而是一个方法Promise需要一次回调,then最多需要两次Promise同步调用其回调,同时then异步调用其回调Promise总是调用它的回调,then可能不会调用它的回调(如果没有履行或拒绝承诺)Promise传递解析/拒绝回调承诺的功能,then传递调用它的承诺的结果值/拒绝原因Promise为了执行副作用(call reject/ resolve)then调用它的回调,调用它们的结果值的回调(用于链接)是的,无论是做回用,虽然他们与其他许多功能(共享特质Promise.resolve,Promise.reject,fetch,...).事实上,所有这些都基于构造Promise函数提供的相同的承诺构造和解析/拒绝功能,尽管这不是它们的主要目的.then基本上提供了附加onFulfilled/ onRejected回调到现有promise的能力,这对于Promise构造函数而言是相当直接的.
两者都利用回调只是巧合 - 不是历史的侥幸,而是语言特征的共同适应.
1:理想情况下,您永远不需要这样,因为所有本机异步API都会返回promise
promise构造函数执行器函数的重点是将解析和拒绝函数传播给非承诺使用代码,将其包装并转换为使用promise.如果你只想将它限制为同步函数,那么是的,可能已经使用了函数的返回值,但这本来是愚蠢的,因为有用的部分是传播解析器并拒绝函数到以后实际运行的代码(返回后的方式),例如传递给某个异步API的回调.
受先前答案的启发(我将介绍最困扰我的部分):
Promise构造函数中的resolve和reject参数不是您定义的函数。可以将它们视为您要嵌入到异步操作代码中的钩子(通常resolve具有成功响应和reject失败原因),因此javascript可以根据异步操作的结果最终将Promise标记为Fulfilled或Rejected ; 一旦发生这种情况,then(fun1, fun2)就会触发您定义的适当功能以使用Promise(fun1(success_response)或fun2(failure_reason),取决于Promise是否已实现/被拒绝)。由于fun1和fun2是普通的旧javascript函数(它们恰好将异步操作的未来结果作为参数),因此它们的return值(可以是undefined 如果您未明确返回)。
另请参阅Mozilla的精彩文章:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Using_promises
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
| 归档时间: |
|
| 查看次数: |
10495 次 |
| 最近记录: |