Promise.resolve与新Promise(resolve)


92

我使用的是bluebird,我看到了两种将同步功能解析为Promise的方法,但是我没有得到两种方法之间的区别。看起来stacktrace有点不同,所以它们不只是一个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);
}

2
Promise.resolve只是糖。
澳洲航空94重型

1
简短答案-用法无差异。只是糖。
Pinal 2014年

@Pinal什么是“糖”?
doubleOrt

5
@金牛座。 语法糖是旨在使事物更易于阅读或表达的语法。参见:维基百科
Wyck

Answers:


82

与评论中的两个答案相反-有所不同。

Promise.resolve(x);

基本上和

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

有一个微妙之处。

承诺返回的函数通常应保证它们不应异步抛出,因为它们可能异步抛出。为了防止出现意外结果和比赛状况,通常将罚球转换为退回的拒绝。

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

如果someObjectundefined什么呢?

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

蓝鸟看到了这一点,佩特卡(Petka)添加Promise.method来解决此问题,因此您可以继续使用返回值。因此,在Bluebird中编写此代码的正确且最简单的方法实际上既不是-而是:

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

Promise.method会为您将引发转换为拒绝,然后返回解决。这是最安全的方法,它可以then通过返回值吸收能力,因此即使someObject实际上是一个承诺,它也可以工作。

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


“承诺返回的函数通常应保证它们不应异步抛出,因为它们可能异步抛出”。您能否继续解释为什么功能应该是同步或异步但不能同时是两者?目前,我喜欢Promise.resolve(),您会说使用Promise.resolve()是反模式吗?
Ashley Coolman

2
@AshleyCoolman请参阅blog.izs.me/post/59142742143/designing-apis-for-asynchrony-一种有时表现为异步的方法应始终保持一致。
本杰明·格伦鲍姆

是否以与using相同的方式Promise.resolve()创建的新实例?如果没有,将会更快并且避免同步抛出。Promisenewreturn Promise.resolve(yourCode)
史蒂文·瓦雄

1
我感到很难受,我使用“ Promise.resolve()。then(function(){/ *可能引发错误的情况* /})。然后...”,以确保错误成为被拒绝的承诺...我将进一步研究“ Promise.method”
Polopollo '16

1
@Polopollo还是Promise.coroutine更有用。
本杰明·格伦鲍姆

16

上面的答案或评论没有提到另一个差异:

如果someObjectPromise,则new 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(resovle => setTimeout(resovle));

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

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

第二个片段将首先打印“ 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调用将首先运行。


参考文献:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.