Promise 构造函数回调是异步执行的吗?
Posted
技术标签:
【中文标题】Promise 构造函数回调是异步执行的吗?【英文标题】:Is the Promise constructor callback executed asynchronously? 【发布时间】:2015-07-09 21:12:46 【问题描述】:假设我有这个代码
function y(resolve, reject)
console.log("Result");
resolve();
var promise = new Promise(y);
我想知道的是函数y
是否会异步执行。
【问题讨论】:
没有。y()
将同步执行。在y()
中,对setTimeout()
、AJAX 请求或类似的调用将导致resolve()
或reject()
被异步执行,但在您发布的代码中并非如此。
因为 Promise 组合良好,并为该行为提供了统一的抽象。否则你只会得到回调汤。仅仅因为组件的行为很简单并不意味着您不需要该组件。例如,Array.forEach
很可能只是一个标准 for 循环。但是Array.forEach
看起来更好,并且允许用户不用担心 for 循环的实现来使用它。
Promise 允许你写 Promise(x).then(y).then(z)
而不是 x(function()y(function()z()))
就是这样。它不会改变 javascript 的基本工作方式
它只是改变了代码的外观。而已。但请记住,易于推理的代码也更易于调试,因此代码的外观并非不重要
当你想组合异步操作时,promise 的好处就很明显了。如果不使用帮助程序库(例如async
),就很难等待一组异步回调。 Promise 还使您能够以几乎与同步代码相同的方式编写异步代码(在 ES6 中使用yield
,我们将更接近这一点)。
【参考方案1】:
这取决于promise的实现。如果我们检查the spec。你可以找到最终的规范here - 因为这个答案最初是写的,所以它已经完成了。
这里是相关摘录(可以找到原文出处here)
-
让完成为 Call(executor, undefined, «resolvingFunctions.[[Resolve]], resolveFunctions.[[Reject]]»)。
如果完成是突然完成,则
让状态为 Call(resolvingFunctions.[[Reject]], undefined, «completion.[[value]]»)。
ReturnIfAbrupt(状态)。
ES6 标准表明承诺的实现是总是异步的(参见第 25.4.5.3 节,Promise.prototype.then
和随附的第 25.4.5.3.1 节,PerformPromiseThen
)。我把相关材料放在下面了。
执行承诺然后
-
否则,如果 Promise 的 [[PromiseState]] 内部槽的值“已完成”,
让 value 为 promise 的 [[PromiseResult]] 内部槽的值。
执行 EnqueueJob("PromiseJobs", PromiseReactionJob, «fulfillReaction, value»)。
否则,如果 Promise 的 [[PromiseState]] 内部槽的值为“rejected”,
让 reason 为 promise 的 [[PromiseResult]] 内部槽的值。
执行 EnqueueJob("PromiseJobs", PromiseReactionJob, «rejectReaction, reason»)。
TLDR:传递给promise的函数是同步执行的,但后续的then
调用总是异步执行的。
【讨论】:
mozilla 版本更容易阅读,因为官方版本是 PDF 格式 我会保留它以防万一,可能会有一些差异,尤其是对未来的读者而言(尽管规范在最终草案中,所以不太可能) 将来,这个答案会过时且无关紧要(我应该知道,我有很多 js 答案从很久以前就这样了):D 希望不是这样。:P 我已将最终的规范草案放入其中,有一个差异,但相当小。 没有官方规范,因为它是草稿。相信我,这不会改变。【参考方案2】:另一个答案证明这一点,但让我谈谈推理:
Promise 构造函数
promise 构造函数回调(在 ES6 规范或构造函数规范库实现中指定)将始终同步执行 - 这是为了在需要时从中提取延迟(旧形式的 Promise 构造)访问resolve
回调:
var r;
var p new Promise(function(resolve, reject)
r = resolve;
);
// use r here, for example
arr.push(r);
then
回调
then
将始终异步执行,几乎所有主流的 Promise 实现(Native、bluebird、$q、Q、when、rsvp、promise、jQuery(截至 3.0)等)以及原生 Promise 都实现(或实现具有更多约束的超集)Promises/A+。
这正是 Promises/A+ 是由 Promises/A 创建的原因。异步保证将被保留,Zalgo 不会被释放。 (另见this post)。
发生这种情况(异步保证)是完全有意,并且主动防止了竞争条件。 then
内外的代码将始终以相同的顺序执行。
以下是相关引述:
在执行上下文堆栈仅包含平台代码之前,不得调用
onFulfilled
或onRejected
。 [3.1]。
【讨论】:
以上是关于Promise 构造函数回调是异步执行的吗?的主要内容,如果未能解决你的问题,请参考以下文章