web-dev-qa-db-ja.com

promise.all()を使用する場合

これは概念的な質問です。 Promiseのデザインパターンは理解していますが、promise.all()に関する質問に答える信頼できるソースが見つかりませんでした。

promise.all()を使用するための正しいシナリオとは

OR

promise.all()を使用するベストプラクティスはありますか?すべてのpromiseオブジェクトが同じまたは類似のタイプである場合にのみ、理想的に使用されるべきですか?

私が考えることができる唯一のものは:

  • 約束を解決する場合はpromise.all()を使用しますonlyifallpromiseオブジェクトの1つでも拒否された場合、解決および拒否します。
18
nikjohn

Promise.all()を使用する場合(および使用しない場合)について、最も一般的な目的の説明を誰かが本当に提供したかどうかはわかりません。

Promise.all()を使用するための正しいシナリオは何ですか

Promise.all()は、複数のpromiseがあり、それらのpromiseが表すすべての操作が正常に終了したときにコードが知りたい場合に役立ちます。個々の非同期操作が何であるかは関係ありません。それらが非同期であり、promiseによって表され、コードがそれらがすべて完了したことを知りたい場合、Promise.all()はまさにそれを行うために構築されます。

たとえば、3つの個別のリモートAPI呼び出しから情報を収集する必要があり、3つのAPI呼び出しすべてから結果が得られたら、3つの結果すべてを使用してさらにコードを実行する必要があるとします。この状況は、Promise.all()に最適です。次のようなことができます:

_Promise.all([apiRequest(...), apiRequest(...), apiRequest(...)]).then(function(results) {
    // API results in the results array here
    // processing can continue using the results of all three API requests
}, function(err) {
    // an error occurred, process the error here
});
_

Promise.all()はおそらく(上記の例のように)同様のタイプの要求で最も一般的に使用されますが、必要な理由はありません。リモートAPIリクエストを作成し、ローカルファイルを読み取り、ローカル温度プローブを読み取る必要がある別のケースがあり、3つの非同期操作すべてからデータがあったときに、すべてのデータを使用して何らかの処理を行いたい場合3、再びPromise.all()を使用します。

_Promise.all([apiRequest(...), fs.readFileAsync(...), readTemperature(...)]).then(function(results) {
    // all results in the results array here
    // processing can continue using the results of all three async operations
}, function(err) {
    // an error occurred, process the error here
});
_

反対に、それらの間で調整する必要がなく、各非同期操作を個別に処理できる場合は、Promise.all()は必要ありません。独自の.then()ハンドラーを使用して、個別の非同期操作をそれぞれ実行するだけで、それらの間の調整は不要です。

さらに、Promise.all()には「高速フェイル」実装と呼ばれるものがあります。最初に渡したプロミスが拒否されるとすぐに拒否するマスタープロミスを返すか、すべてのプロミスが解決したときに解決します。したがって、Promise.all()を使用するには、そのタイプの実装が状況に応じて機能する必要があります。他の状況では、複数の非同期操作を実行する必要があり、それらの一部が失敗した場合でも、すべての結果が必要です。 Promise.all()はあなたのためにそれを直接行いません。代わりに、そのような状況ではおそらくPromise.settle()のようなものを使用します。 ここで.settle()の実装 を見ることができます。これにより、一部の結果が失敗しても、すべての結果にアクセスできます。これは、一部の操作が失敗する可能性があり、成功した操作の結果を追跡する有用なタスクがある場合、またはそれに基づいて決定できなかったすべての操作の失敗理由を調べたい場合に特に役立ちます。

Promise.all()を使用するベストプラクティスはありますか?すべてのpromiseオブジェクトが同じまたは類似のタイプである場合にのみ、理想的に使用されるべきですか?

上記で説明したように、個々の非同期操作が何であるか、またはそれらが同じタイプであるかは関係ありません。あなたのコードがそれらを調整し、それらすべてがいつ成功するかを知る必要があるかどうかだけが重要です。


notPromise.all()を使用する場合の状況をリストすることも役立ちます。

  1. 非同期操作が1つしかない場合。 1つの操作だけで、1つのプロミスで.then()ハンドラーを使用できますが、Promise.all()を使用する理由はありません。
  2. 複数の非同期操作間で調整する必要がない場合。
  3. 高速な実装が適切でない場合。すべての結果が必要な場合、たとえ一部が失敗しても、Promise.all()はそれ自体を行いません。おそらく、代わりにPromise.settle()のようなものが必要になるでしょう。
  4. 非同期操作がすべてプロミスを返さない場合、Promise.all()はプロミスで管理されていない非同期操作を追跡できません。
49
jfriend00

Promise.allは、複数のPromiseが並行して(同時に)解決するのを待つためのものです。入力Promiseのすべてが解決されたときに解決するPromiseを返します。

// p1, p2, p3 are Promises
Promise.all([p1, p2, p3])
  .then(([p1Result, p2Result, p3Result]) => {
    // This function is called when p1, p2 and p3 have all resolved.
    // The arguments are the resolved values.
  })

入力Promiseのanyが拒否された場合、Promise.allによって返されたPromiseも拒否されます。

一般的なシナリオは、いくつかのAPIリクエストが完了するのを待っているため、それらの結果を組み合わせることができます。

 const contentPromise = requestUser();
 const commentsPromise = requestComments();

 const combinedContent = Promise.all([contentPromise, commentsPromise])
   .then(([content, comments]) => {
     // content and comments have both finished loading.
   })

PromiseインスタンスでPromise.allを使用できます。

3
joews

これらの質問は、言語機能の利用可能なAPIを使用するときに自分自身で回答する傾向があるため、これらの質問に回答することは困難です。基本的に、Promisesを anti-patterns を回避する限り、ユースケースに合った方法で使用しても構いません。

Promise.all()を使用するための正しいシナリオは何ですか

操作が複数のプロミスの成功した解決に依存する状況。

Promise.all()を使用するベストプラクティスはありますか?すべてのpromiseオブジェクトが同じまたは類似のタイプである場合にのみ、理想的に使用されるべきですか?

一般的に、いいえ。

2
sdgluck

APIにいくつかのリクエストを行う必要があるときにpromise.all()を使用し、アプリケーションがリクエストされたすべてのデータを読み込む前に何かを表示したくないので、すべてのデータを取得するまで実行フローを遅らせます必要。

例:

やりたいことアプリのユーザーとその商品をロードして(複数のリクエストを行う必要があると想像して)、ユーザーのメールと商品名でアプリのテーブルを表示したい各ユーザー。

次に行うこと APIに要求を送信し、約束を作成し、promise.all()を使用します

すべてのデータが読み込まれたときの処理データがアプリに到着したら、promises.all()のコールバックを実行し、ユーザーにテーブルを表示できます。

promises.all()を使用するのが理にかなっているシナリオを確認するのに役立つことを願っています

2
miquelarranz

Promise.allは、渡された反復可能オブジェクトのすべてのプロミスから値の配列を渡します。

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

var isCallFailed = false;
function myEndpoint1() {
  return isCallFailed ? Promise.reject("Bohoo!") :Promise.resolve({"a":"a"});
}
function myEndpoint2() {
  return Promise.resolve({"b":"b"});
}

Promise.all([myEndpoint1(), myEndpoint2()])
.then(values => {
  var data1 = values[0];
  var data2 = values[1];
  alert("SUCCESS... data1: " + JSON.stringify(data1) + "; data2: " +  JSON.stringify(data2));
})
.catch(error => {
  alert("ERROR... " + error);
});

isCallFailed = trueを作成して別のケースを試すことができます。

0
Venky

Promise.all-このメソッドは、複数のプロミスが完了するのを待ちたい場合、またはPromise.all(iterable)メソッドが、反復可能な引数内のすべてのプロミスが解決されるか、または拒否された最初の渡された約束の理由。

2.Promise.all(files).catch(err => {})を使用します。いずれかのプロミスが拒否された場合、エラーがスローされます。

3.すべての約束が拒否または履行されるのを待ちたい場合は、.allの前の約束で.reflectを使用します

  1. 構文-Promise.all(iterable);
0
Nancy thakkar

私はこのような何かのためにすべてを約束する傾向があります:

_myService.getUsers()
   .then(users => {
       this.users = users;

       var profileRequests = users.map(user => {
           return myService.getProfile(user.Id); // returns a promise
       });

       return Promise.all(profileRequests);
   })
   .then(userProfilesRequest => {
       // do something here with all the user profiles, like assign them back to the users.

       this.users.forEach((user, index) => {
           user.profile = userProfilesRequest[index];
       });
   });
_

ここでは、ユーザーごとにプロファイルを取得します。 xの量のプロミスを解決できるようになったので、私のプロミスチェーンが手に負えないようにしたくありません。

したがって、Promise.all()は基本的にすべての約束を1つに集約し、次のthenでそれを管理できます。これは、関連する設定などを取得したいプロファイルごとになど、限り続けることができます。さらに多くの約束を作成するたびに、それらをすべて1つにまとめることができます。

0