Promise.resolveと新しいPromise(resolve)


93

私はbluebirdを使用していますが、同期関数をPromiseに解決する方法は2つありますが、両方の方法の違いはわかりません。スタックトレースが少し違うように見えるので、それらは単なるではありません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);
}

3
Promise.resolve砂糖だけです。
カンタス航空94ヘビー

1
短い答え-使用方法の違いはありません。砂糖だけ。
ピナル2014年

@Pinal「砂糖」とは何ですか?
doubleOrt 2018年

5
@おうし座。 構文シュガーは、物事を読みやすくしたり表現したりするために設計された構文です。参照:ウィキペディア
Wyck、2018年

回答:


82

コメントの両方の答えに反して-違いがあります。

ながら

Promise.resolve(x);

基本的に同じです

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

微妙です。

Promiseの戻り関数は、非同期でスローされる可能性があるため、通常は同期でスローされないことが保証されている必要があります。予期しない結果と競合状態を防止するために、スローは通常、返された拒否に変換されます。

これを念頭に置いて-仕様が作成されたとき、promiseコンストラクターは安全です。

何場合はsomeObjectありますかundefined

  • 方法Aは拒否された約束を返します。
  • ウェイBは同期的にスローします。

Bluebirdはこれを認識し、PetkaがPromise.methodこの問題に対処するために追加したので、戻り値を使い続けることができます。したがって、Bluebirdでこれを記述する最も簡単で正しい方法は、実際にはどちらでもありません。

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

Promise.methodは、スローをリジェクトに変換し、リゾルブに戻ります。これはこれを行うのに最も安全な方法であり、then戻り値を介してテーブルを同化するためsomeObject、実際にはそれ自体がプロミスである場合でも機能します。

一般に、Promise.resolveオブジェクトと外部プロミス(Thenables)をプロミスにキャストするために使用されます。それがユースケースです。


「Promiseの戻り関数は、非同期でスローされる可能性があるため、通常は同期でスローされないことが保証されているはずです」関数が同期または非同期のいずれかであって、両方ではない理由を詳しく説明していただけますか?現在、私はPromise.resolve()を楽しんでいますPromise.resolve()が、アンチパターンを使用していると言っていいでしょうか?
アシュリークールマン2016年

2
@AshleyCoolman blog.izs.me/post/59142742143/designing-apis-for-asynchronyを参照してください。非同期的に動作することがあるメソッドは、一貫性を保つために常にそうする必要があります。
Benjamin Gruenbaum

Promise.resolve()の新しいインスタンスを作成してPromise使用するのと同じようにnew?そうでなければ、return Promise.resolve(yourCode)より速く、同期スローを回避します。
Steven Vachon、2016

1
私は気分が悪いのですが、 "Promise.resolve()。then(function(){/ * case that throw a error * /})。then ..."を使用して、エラーが拒否されたpromiseになることを確認しています... 「Promise.method」の詳細を調べます
Polopollo

1
@PolopolloまたはPromise.coroutineそれはさらに便利です。
Benjamin

16

上記の回答やコメントでは言及されていない別の違いがあります:

場合someObjectPromisenew Promise(resolve)二つの追加ダニの費用がかかるでしょう。


次の2つのコードスニペットを比較します。

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

2番目のスニペットは、最初に「ティック3」を出力します。どうして?

  • 値がpromiseの場合、Promise.resolve(value)正確に値を返します。Promise.resolve(value) === value本当だろう。MDNを参照

  • しかしnew Promise(resolve => resolve(value))value約束に従うためにロックされている新しい約束を返します。「ロックイン」を行うには、追加の1ティックが必要です。

    // 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コールは実行されます。


参照:

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.