Promise 的主体什么时候执行?

IT技术 javascript ecmascript-6 promise es6-promise
2021-02-02 02:46:49

假设我有以下内容Promise

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

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

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

4个回答

立即,是的,按规范。

来自MDN

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

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

这种保证可能很重要,例如,当您准备多个Promise然后传递给all或 时race,或者当您的执行器具有同步副作用时。

似乎 MDN 和 ES 规范不再这么说,但我认为您仍然可以假设它运行同步,因为步骤 1-11 提到返回一个Promise,您确实会同步返回。它没有提到异步运行它或将它排队到某个地方,就像PerformPromiseThen所说的“将履行反应作为......的最后一个元素”。
2021-03-13 02:46:49
一下子就糊涂了。执行器实际上是由 Promise 构造函数同步调用的
2021-04-12 02:46:49

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

一般来说,你不会promise像你当前的实现那样真正使用 a ,它仍然是同步的。

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

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

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

您可以从下面看到,只需将同步代码而不是异步代码放入主体中,主体就会立即执行:

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

除了在Promise完成之前的不确定延迟和可以调用“then”(点“c”)之外,同样处理主体中的异步代码。所以 'a' 和 'b' 将在doSomethingAsynchronous()返回后立即打印,但 'c' 仅在 Promise 完成时出现(调用 'resolve')。

表面上看起来很奇怪,一旦添加了对 'then' 的调用,'b' 打印在 'c' 之前,即使一切都是同步的。肯定会打印“a”,然后是“c”,最后是“b”?'a', 'b' 和 'c' 之所以按这个顺序打印是因为无论 body 中的代码是 async 还是 sync ,'then' 方法总是被 Promise 异步调用。

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

从 Promise 规范中看不出它为什么这样做。我的猜测是它确保了关于何时调用 'then' 的一致行为(总是在当前执行线程完成之后),这大概是允许在连续启动Promises所有then调用之前将多个堆叠/链接在一起

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

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

考虑以下代码:

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

}
const myPromise = new Promise(executorFunction);

当我们执行上面的代码时, executorFunction 会在我们声明 promise 的时候自动调用,而无需我们显式调用它。