Promise.resolve 与新的 Promise(resolve)

Posted

技术标签:

【中文标题】Promise.resolve 与新的 Promise(resolve)【英文标题】:Promise.resolve vs new Promise(resolve) 【发布时间】:2014-12-29 22:22:27 【问题描述】:

我正在使用 bluebird,我看到了两种将同步函数解析为 Promise 的方法,但我不明白这两种方法之间的区别。看起来堆栈跟踪有点不同,所以它们不仅仅是alias,对吧?

那么首选的方式是什么?

方式A

function someFunction(someObject) 
  return new Promise(function(resolve) 
    someObject.resolved = true;
    resolve(someObject);
  );

方式 B

function someFunction(someObject) 
  someObject.resolved = true;
  return Promise.resolve(someObject);

【问题讨论】:

Promise.resolve 只是糖。 简短回答 - 用法没有差异。只是糖。 @Pinal 什么是“糖”? @Taurus。 语法糖 是旨在使事物更易于阅读或表达的语法。见:wikipedia. 【参考方案1】:

与 cmets 中的两个答案相反 - 存在差异。

虽然

Promise.resolve(x);

基本一样

new Promise(function(r) r(x); );

有一个微妙之处。

Promise 返回函数通常应该保证它们不应该同步抛出,因为它们可能会异步抛出。为了防止意外的结果和竞争条件 - 抛出通常会转换为返回的拒绝。

考虑到这一点 - 创建规范时,promise 构造函数是安全的。

如果someObjectundefined 怎么办?

方式 A 返回一个被拒绝的承诺。 方式 B 同步投掷。

Bluebird 看到了这一点,Petka 添加了Promise.method 来解决此问题,以便您可以继续使用返回值。因此,在 Bluebird 中编写此代码的正确和最简单的方法实际上都不是——它是:

var someFunction = Promise.method(function someFunction(someObject)
    someObject.resolved = true;
    return someObject;
);

Promise.method 将为您将 throws 转换为 rejects 并返回为 resolves。这是最安全的方法,它通过返回值同化thenables,因此即使someObject 实际上是一个承诺本身,它也可以工作。

一般来说,Promise.resolve 用于将对象和外部承诺(thenables)转换为承诺。这就是它的用例。

【讨论】:

“Promise 返回函数通常应该保证它们不应该同步抛出,因为它们可能会异步抛出”。您能否详细说明为什么函数应该是同步的或异步的,而不是两者兼而有之?目前我喜欢 Promise.resolve(),你会说使用 Promise.resolve() 是一种反模式吗? @AshleyCoolman 请参阅blog.izs.me/post/59142742143/designing-apis-for-asynchrony - 一种有时行为异步的方法应该始终这样做以保持一致性。 Promise.resolve() 是否以与使用new 相同的方式创建Promise 的新实例?如果没有,return Promise.resolve(yourCode) 会更快并避免同步抛出。 我感觉不好,我使用“Promise.resolve().then(function() /*case that can throw an error*/).then...”来确保错误变成了被拒绝的承诺......我会更多地研究“Promise.method” @Polopollo 或 Promise.coroutine 更有用。【参考方案2】:

上面的答案或cmets没有提到另一个区别:

如果 someObject Promisenew Promise(resolve) 将花费两个额外的滴答声。

比较以下两个代码 sn -p:

const p = new Promise(resovle => setTimeout(resovle));

new Promise(resolve => resolve(p)).then(() => 
  console.log("tick 3");
);

p.then(() => 
  console.log("tick 1");
).then(() => 
  console.log("tick 2");
);

const p = new Promise(resolve => setTimeout(resolve));

Promise.resolve(p).then(() => 
  console.log("tick 3");
);

p.then(() => 
  console.log("tick 1");
).then(() => 
  console.log("tick 2");
);

第二个 sn-p 将首先打印 'tick 3'。为什么?

如果值是一个承诺,Promise.resolve(value) 将准确返回值。 Promise.resolve(value) === value 是真的。见MDN

但是new Promise(resolve => resolve(value)) 将返回一个新的承诺,该承诺已锁定以遵循value 承诺。它需要一个额外的勾号才能“锁定”。

  // something like:
  addToMicroTaskQueue(() => 
    p.then(() => 
      /* resolve newly promise */
    )
      // all subsequent .then on newly promise go on from here
      .then(() => 
        console.log("tick 3");
      );
  );

tick 1 .then 调用将首先运行。

参考: http://exploringjs.com/es6/ch_promises.html#sec_demo-promise

【讨论】:

以上是关于Promise.resolve 与新的 Promise(resolve)的主要内容,如果未能解决你的问题,请参考以下文章

Promise.resolve()的参数分4种情况

.resolve() 和 .promise() 有啥区别?

Promise.resolve()与new Promise(r =; r(v))

Promise.resolve 是异步函数吗?

Promise静态方法实现(all race finally resolve reject)

javascript Promise.resolve和Promise.reject示例