Promise.resolve vs new Promise(resolve)

2022-08-30 04:51:42

我正在使用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);
}

答案 1

与评论中的两个答案相反 - 有区别。

Promise.resolve(x);

基本相同

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

有一个微妙之处。

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

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

如果是 ?someObjectundefined

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

Bluebird看到了这一点,Petka也加入了这个问题,这样你就可以继续使用返回值。因此,在Bluebird中编写此内容的正确和最简单的方法实际上都不是 - 它是:Promise.method

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

Promise.method 会将抛出转换为拒绝,并将返回转换为解析。这是最安全的方法来做到这一点,它通过返回值吸收,所以即使实际上是一个承诺本身,它也会起作用。thensomeObject

通常,用于将对象和外来承诺(thenables)投射到承诺中。这就是它的用例。Promise.resolve


答案 2

还有另一个区别,上面的答案或评论没有提到:

如果某个对象是一个 Promise那么新的 Promise(resolve) 将额外花费两个刻度。


比较以下两个代码片段:

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");
});

第二个代码段将首先打印“勾选 3”。为什么?

  • 如果该值是承诺,则将完全返回值。 会是真的。参见 MDNPromise.resolve(value)Promise.resolve(value) === value

  • 但会返回一个新的承诺,它已经锁定了,以遵循承诺。它需要额外的一个刻度来使“锁定”。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 调用将首先运行。


引用: