承诺的身体什么时候被执行?

时间:2017-02-08 16:45:11

标签: javascript ecmascript-6 promise es6-promise

假设我有以下Promise

function doSomethingAsynchronous() {
  return new Promise((resolve) => {
    const result = doSomeWork();

    setTimeout(() => {
      resolve(result);
   }), 100);
  });
}

在哪个时间点doSomeWork()被调用?它是在Promise构建之后还是紧随其后?如果没有,我是否还需要做一些明确的事情来确保Promise的主体运行?

5 个答案:

答案 0 :(得分:32)

立即,是的,按照规范。

来自the MDN

  

执行函数由Promise实现立即执行,传递resolve和reject函数(在Promise构造函数甚至返回创建的对象之前调用执行程序)

这是ECMAScript规范中的内容(当然难以阅读......):http://www.ecma-international.org/ecma-262/6.0/#sec-promise-executor

这种保证可能很重要,例如,当您准备好几个承诺,然后传递给allrace,或者当执行者有同步副作用时。

答案 1 :(得分:5)

是的,当您构造Promise时,第一个参数会立即执行。

一般情况下,你不会像你当前的实现一样使用promise,它仍然是同步的。

您宁愿使用超时实现它,或者将resolve函数作为ajax回调的一部分调用

function doSomethingAsynchronous() {
  return new Promise((resolve) => {
    setTimeout(function() {
      const result = doSomeWork();
      resolve(result);
    }, 0);
  });
}

然后setTimeout方法将在事件队列空闲的下一个可能时刻调用该函数

答案 2 :(得分:1)

您可以从下面看到,只需在主体中放置同步代码而不是异步即可立即执行主体

function doSomethingAsynchronous() {
  return new Promise((resolve) => {
    console.log("a");
    resolve("promise result");
  });
}
doSomethingAsynchronous();console.log("b");

结果显示promise主体将立即执行(在打印“ b”之前):

a
b

Promise的结果将保留,例如,将其释放给'then'调用:

doSomethingAsynchronous().then(function(pr){console.log("c:"+pr);});console.log("b");

结果:

a
b
c:promise result

主体中对异步代码的处理相同,除了在实现诺言和可以调用“ then”之前不确定的延迟(点“ c”)。因此,doSomethingAsynchronous()返回时将立即打印“ a”和“ b”,但仅在实现诺言(称为“ resolve”)时才会显示“ c”。

添加了对“ then”的调用后,表面上看起来很奇怪的是,即使一切都是同步的,在“ c”之前也会打印“ b”。肯定会打印“ a”,然后打印“ c”,最后打印“ b”吗?之所以按此顺序打印“ a”,“ b”和“ c”是因为无论主体中的代码是异步还是同步,Promise始终会异步调用“ then”方法。

在我的脑海中,我想象一旦调用了'resolve',Promise中的setTimeout(function(){then(pr);},0);之类的东西就会调用'then'方法。即当前执行路径必须在传递给'then'的函数执行之前完成。

从Promise规范中不知道为什么这么做。我的猜测是,它可以确保何时调用“ then”(始终在当前执行线程完成后)方面保持一致的行为,这大概可以在启动所有Promises调用之前将多个then堆叠/链接在一起

答案 3 :(得分:1)

根据EcmaScript规范 http://www.ecma-international.org/ecma-262/6.0/#sec-promise-executor

  

执行程序功能由Promise立即执行   实现,传递解决和拒绝功能(执行器是   在Promise构造函数甚至返回创建的对象之前调用)

考虑以下代码:

var executorFunction = (resolve, reject) => {
    console.log("This line will be printed as soon as we declare the promise");
    if(asynkTaskCompleted){
        resolve("Pass resolved Value here");
    }else{
        reject("Pass reject reason here");
    }

}
const myPromise = new Promise(executorFunction);

当我们执行上述代码时,只要声明了诺言,便会自动调用executorFunction,而无需显式调用它。

答案 4 :(得分:-1)

是的,因为呼叫是同步的,所以在附加任何“.then”或“.catch”之前会立即调用它。

承诺将在第一个“.then”附加时解决,并立即传递解析值。