【问题标题】:Promise.resolve vs Promise.resolve().then()Promise.resolve 与 Promise.resolve().then()
【发布时间】:2021-11-30 09:50:52
【问题描述】:

之前在这里提出的一个问题,与这个问题的标题完全相同,被回答为“你不应该使用它,而是使用它”,我想知道它的作用,而不是我还能做什么,这是关于理解而不是简单的复制粘贴。

我的问题很简单,这三种方法在创建promise时有什么区别?

const API = (item, fail) =>
  new Promise((resolve, reject) => {
    if (fail) reject(item + ' ...with an error');
    setTimeout(() => resolve(item), 1000);
  });

(async () => {
  const pro1 = Promise.resolve(API('I am inside resolve'));
  const pro2 = Promise.resolve(API('I am inside resolve', true));

  const pro3 = Promise.resolve().then(() => API('I am thenable'));
  const pro4 = Promise.resolve().then(() => API('I am thenable', true));

  const pro5 = new Promise((resolve) => resolve(API('I am a new promise')));
  const pro6 = new Promise((resolve) => resolve(API('I am a new promise', true)));

  const store = [pro1, pro2, pro3, pro4, pro5, pro6];

  const results = await Promise.allSettled(store);

  for (const { status, value, reason } of results) {
    if (status === 'fulfilled') console.log(value)
    else console.log(reason)
  }
})();

【问题讨论】:

  • 好吧,如果API 总是返回一个承诺,那根本没有区别。当它返回一个普通值或抛出异常时,它很重要。
  • 查看this的答案。
  • @Bergi,所以如果我这样做const pro = API('I am a promise anyway') 会是相同的,如果该功能是远离承诺?
  • @Álvaro 是的,如果你知道API 总是返回一个承诺,那么Promise.resolve 的东西都不是必需的
  • @Álvaro 如果您调用异步函数或始终返回 Promise 的函数,您可以编写 const store = [API("I'm a new promise")] 而不使用 Promise.resolve 或其他额外的 Promise 包装。但如果这是你一直在问的,那就不清楚了。最好澄清一下,这将对其他用户有所帮助。

标签: javascript es6-promise


【解决方案1】:

区别在于要完成的工作。虽然所有这些方法都是有效的,但它们的成本和可预测性不同。

  1. Promise.resolve() 生成单个解析的 Promise 实例,并根据提供给调用 JS 引擎的值有信息来优化它。它使所有工作都在对 JS 引擎的底层代码(通常是 C++,但可能是 Java 或 WASM)的一次调用中完成。所以它永远是最好的选择。
  2. Promise.resolve().then(() => API(/*...*/)) 产生多个 Promise 实例:一个在 Promise.resolve() 另一个在 .then() 调用。它还分配更多内存并在 JS 和引擎之间进行多次(3 次或更多)冗余跳转。它几乎不可优化,需要执行密集的启发式算法才能确定此调用是否可优化。这是最糟糕的选择。
  3. new Promise((resolve) => resolve(API(/* ... */)) 分配一个函数和一个 Promise 实例,在 JS 和引擎之间进行两次跳转。由于 JS 的性质,优化此调用更加困难。

【讨论】:

  • "JS 引擎的底层代码" 也可以用 JS 编写——为了更好的可优化性和更少的上下文切换。
  • @Bergi 感谢您的加入。我同意你的看法,但在这种特殊情况下,从 JS 方面超越 Promise.resolve() 几乎是不可能的。
【解决方案2】:
Promise.resolve().then() 

在您的示例中,then() 没有任何区别,因为您只需解决承诺并获取其数据。

then() 通常用于链式 promise,以此为例:

Promise.resolve('foo')
  // 1. Receive "foo", concatenate "bar" to it, and resolve that to the next then
  .then(function(string) {
    return new Promise(function(resolve, reject) {
      setTimeout(function() {
        string += 'bar';
        resolve(string);
      }, 1);
    });
  })
  // 2. receive "foobar", register a callback function to work on that string
  // and print it to the console, but not before returning the unworked on
  // string to the next then
  .then(function(string) {
    setTimeout(function() {
      string += 'baz';
      console.log(string); // foobarbaz
    }, 1)
    return string;
  })

在这里,我们将多个 Promise then() 链接到之前解决的 Promise 中,同时保留第一次解决的原始数据,尽管在这种情况下,我们会使用每个新的 Promise 对其进行修改。

您可以阅读有关承诺和链接的更多信息here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-23
    • 2017-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-20
    相关资源
    最近更新 更多