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

Lud*_*ven 78 javascript promise ecmascript-6 es6-promise

据我所知,promise是可以解决()或拒绝()但我很惊讶发现在调用解析或拒绝后,promise中的代码继续执行.

我认为解决或拒绝是退出或返回的异步友好版本,这将停止所有立即执行功能.

有人可以解释为什么以下示例有时会在解析调用后显示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");
});
Run Code Online (Sandbox Code Playgroud)

jsbin

Fel*_*ing 121

JavaScript具有"运行到完成"的概念.除非抛出错误,否则执行函数直到达到return语句或其结束.函数外部的其他代码不能干扰它(除非再次抛出错误).

如果要resolve()退出初始化函数,则必须通过return以下方式添加前缀:

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

  • @Bergi,在你的编辑中,你说"return resolve();" 这似乎很不寻常.为了说服自己没有重要的事情,我必须阅读文档并看到(1)resolve()似乎没有返回任何后果,并且(2)初始化回调的返回值没有似乎被使用了.说"resolve(); return;"不是更清楚吗?从而避免这种分心? (9认同)
  • @Alnitak`resolve`本身不是异步的,它是完全同步的.尽管严格使用ES6 API,但无法观察它是同步还是异步. (3认同)
  • @Esilija 好的,也许我不清楚。有些人认为调用 `resolve` 会导致任何注册的回调被立即调用,这样它们就成为当前调用堆栈的一部分。这不是真的,它只是将回调排队(你是对的,它不是异步的,但它只是做它的事情并立即终止) (2认同)

Aln*_*tak 19

当规则resolve仍然需要异步调用时,将在您的promise 时调用的回调.这是为了确保将promises用于混合的同步和异步操作时的一致行为.

因此,当您调用resolve回调队列时,函数会立即继续执行调用后的任何代码resolve().

只有在给予JS事件循环后,才能将回调从队列中删除并实际调用.

  • @thefourtheye:事件循环规范实际上是[HTML5](http://www.w3.org/TR/html5/webappapis.html#event-loops)的一部分.ES6定义了一个名为[**`EnqueueJob`**]的内部方法(https://people.mozilla.org/~jorendorff/es6-draft.html#sec-enqueuejob),由[**`.then调用`**](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-promise.prototype.then). (5认同)
  • @FelixKling它的微任务/宏任务,这里是规范中"延迟"的部分"当没有正在运行的执行上下文且执行上下文堆栈为空时,ECMAScript实现从作业队列中删除第一个PendingJob并使用包含的信息在其中创建执行上下文并开始执行相关的Job抽象操作." (2认同)