【问题标题】:When is the body of a Promise executed?Promise 的主体何时执行?
【发布时间】:2017-06-26 09:53:18
【问题描述】:

假设我有以下Promise

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

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

doSomeWork() 在哪个时间点被调用?是在构造Promise 之后立即还是在构造之后?如果没有,是否需要明确执行其他操作以确保 Promise 的主体运行?

【问题讨论】:

标签: javascript ecmascript-6 promise es6-promise


【解决方案1】:

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

executor 函数由 Promise 立即执行 实现,传递解析和拒绝函数(执行者是 在 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);

当我们执行上述代码时,一旦我们声明了 Promise,executorFunction 就会被自动调用,而无需我们显式调用它。

【讨论】:

    【解决方案2】:

    马上,是的,按照规范。

    来自the MDN

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

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

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

    【讨论】:

    • 立即 令人困惑。执行器实际上是由 Promise 构造函数同步调用的。
    • 似乎 MDN 和 ES 规范不再这么说了,但我认为你仍然可以假设它运行同步,因为步骤 1-11 提到返回一个承诺,你确实会同步返回.它没有提到异步运行它或在某个地方排队,就像PerformPromiseThen 所说的“将fulfillReaction 作为...的最后一个元素”。
    【解决方案3】:

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

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

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

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

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

    【讨论】:

      【解决方案4】:

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

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

      结果显示承诺正文立即执行(在打印 '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”仅在承诺完成时出现(调用“resolve”)。

      表面上看起来很奇怪,一旦添加了对 'then' 的调用,即使所有内容都是同步的,'b' 也会在 'c' 之前打印。当然'a'会打印,然后是'c',最后是'b'? 'a', 'b' 和 'c' 之所以按顺序打印是因为无论主体中的代码是异步还是同步,Promise 总是异步调用 'then' 方法。

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

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

      【讨论】:

        猜你喜欢
        • 2017-12-05
        • 1970-01-01
        • 2016-03-11
        • 1970-01-01
        • 2017-02-20
        • 1970-01-01
        • 2016-08-07
        • 2020-03-13
        相关资源
        最近更新 更多