解决后,为什么javascript ES6 Promises继续执行?


97

据我了解,promise是可以resolve()或reject()的东西,但令我惊讶的是,发现promise中的代码在调用了resolve或reject之后仍继续执行。

我认为resolve或reject是exit或return的异步友好版本,它将终止所有立即执行的函数。

有人可以解释为什么下面的示例有时会在resolve调用后显示console.log的原因:

var call = function() {
    return new Promise(function(resolve, reject) {
        resolve();
        console.log("Doing more stuff, should not be visible after a resolve!");
    });
};

call().then(function() {
    console.log("resolved");
});

jsbin


12
合理的问题,但是话又说回来,JS就像您告诉它一样,只执行一个语句。resolve()不是一个神奇地具有效果的JS控制语句return,它只是一个函数调用,是的,执行之后会继续执行。

这是一个很好的问题,即使阅读了所有答复,我也不确定最佳实践……
Gabriel Glenn

我认为误解是由您到底使用resolve()终止而来的:在您调用resolve()之后,promise已被解决,但是正如其他人已经说过的那样,这并不意味着终止了promise的函数已经终止了它的终止。任务也是如此,因此它将持续到达到“正常”终止为止。
朱塞佩·贝通

Answers:


143

JavaScript具有“从头到尾的概念。除非抛出错误,否则函数将一直执行到return语句或其结尾。该函数之外的其他代码不会对此造成干扰(除非再次抛出错误)。

如果要resolve()退出初始化函数,则必须在其前面加上return

return new Promise(function(resolve, reject) {
    return resolve();
    console.log("Not doing more stuff after a return statement");
});

嗨,费利克斯(Felix)-我认为这只是故事的一部分-另一部分resolve()本身就是异步功能。正如我们在另一个(已删除的)答案中所看到的,有人认为调用resolve会立即运行任何回调。
Alnitak'3

3
@Alnitak resolve本身不是异步的,它是完全同步的。尽管严格使用ES6 API,但无论是同步还是异步都无法观察到。
Esailija

1
@Esailija好的,也许我不清楚。有人认为,调用resolve将导致任何已注册的回调立即被调用,从而使它们成为当前调用堆栈的一部分。这是不对的,相反,它只是将回调排队(您是对的,它不是异步的,但是它只是在做它的事情并立即终止)
Alnitak

@Alnitak:我明白你在说什么。我只是将其解释为为什么console.log显示在而不是为什么它按该顺序显示。到目前为止,做什么resolve和如何作出承诺与我对问题的解释方式无关。但是,当然,在承诺的背景下进行了解仍然很重要。我支持您的回答的原因之一:)
Felix Kling

9
@Bergi,在您的编辑中,您说“ return resolve();”。这似乎很不寻常。为了说服自己没有什么要紧的,我不得不阅读文档,并看到(1)resolve()似乎没有返回任何后果,(2)初始化回调的返回值没有似乎被使用了。说“ resolve(); return;”会更清晰吗?从而避免这种分心?
唐·哈奇

19

resolve规范仍然要求在您承诺时将调用的回调被异步调用。这是为了确保在将诺言用于同步和异步操作混合时确保行为一致。

因此,当您调用resolve回调函数时,该队列排队,并且函数执行会随resolve()调用之后的任何代码立即继续执行。

只有将JS事件循环给予了返回控制,才可以从队列中删除回调并实际调用该回调。


1
回调队列记录在A +规范或ES6中?
thefourtheye

5
@thefourtheye:事件循环规范实际上实际上是HTML5的一部分。ES6定义了一个称为的内部方法EnqueueJob,该方法由调用.then
Felix Kling

@thefourtheye:实际上,ES6似乎也定义了队列:people.mozilla.org/~jorendorff/…。我猜想与事件循环有关的一种或另一种方式。
菲利克斯·克林

@FelixKling感谢您的链接-我知道它是这样工作的,但无法引用章节和经文
Alnitak

2
@FelixKling是微任务/宏任务,这是规范中的“延迟”部分。在其中创建执行上下文并开始执行相关的Job抽象操作。”
本杰明·格林鲍姆
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.