ホームページ  >  記事  >  ウェブフロントエンド  >  Promise.all( ) のジレンマ: それが役に立つときと、それが苦痛になるとき

Promise.all( ) のジレンマ: それが役に立つときと、それが苦痛になるとき

Susan Sarandon
Susan Sarandonオリジナル
2024-09-21 16:30:03528ブラウズ

The Promise.all( ) Dilemma: When it helps and When it hurts

最新の JavaScript 開発では、非同期操作の処理が一般的なタスクです。 API リクエストの作成、データベースのクエリ、ファイルの読み取りなど、非同期コードの操作はほぼ避けられません。開発者がよく目にするツールの 1 つは Promise.all() です。しかし、私も含め、私たちの多くは、Promise.all() があるという理由だけで、それが特定のユースケースにとって最適なソリューションであるかどうかをよく理解せずに使おうとする罠に陥る可能性があります。

1. Promise.all() の流行に乗る

開発者は、新しい機能やツールに遭遇し、それらをどこにでも実装する必要があると考えがちです。 Promise.all() でこの状況に陥ったことに気づきました。複数の Promise を並行して実行し、すべての Promise が完了するまで待ってから続行する方法について読んだので、それを自分のコードに統合したいと思いました。必要性もよく分からないまま、できるところから便乗して適用してみました。

これは強力なツールなので、より単純な代替手段よりも優れているに違いないと考えるのは簡単です。しかし、すぐに気づきましたが、コンテキストを考慮せずにやみくもに Promise.all() を適用しても、常に最も効率的で読みやすいコードが得られるわけではありません。

2. 非同期 JavaScript の基礎

Promise.all() が役立つ場合について詳しく説明する前に、まず JavaScript で非同期関数がどのように機能するかを見てみましょう。 async 関数を作成して await を使用すると、JavaScript によりコードの残りの部分をブロックすることなくその操作が実行されます。これは、1 つの操作を開始し、結果を待っている間に他の操作に進むことができることを意味します。

しかし、注意しないと、独立して実行できる操作を相互に不必要に依存させてしまう可能性があります。 Promise.all() でこの状況に陥ったことに気づき、すべての非同期関数を並行して実行することが常に良い考えであると考えました。

例: 非同期関数の逐次実行

const fetchData = async () => {
  const data1 = await getChart();   // Request #1
  const data2 = await getDetails(); // Request #2
};

コード内で data1 と data2 が次々にフェッチされても、ブラウザーは両方のリクエストを非同期かつほぼ同時に開始します。実際、[ネットワーク] タブを確認すると、両方のリクエストがほぼ同時に開始されていることがわかりました。これにより、JavaScript はすでに物事を並列処理しており、Promise.all() は必ずしも必要ではないことがわかりました。

3. Promise.all() をいつ使用する必要がありますか?

最初はどこでも Promise.all() を使おうと急いでいたにもかかわらず、それが本当に輝く状況があります。これは、先に進む前に複数の非同期操作が完了するまで待つ必要がある場合に特に便利です。

Promise.all() を使用する理由

  1. すべての Promise を待機: 複数の非同期タスクの結果が相互に依存している場合、または続行する前にすべてのタスクを完了する必要がある場合は、Promise.all() が最適です。
  2. エラー処理: Promise.all() はすぐに失敗します。つまり、Promise が失敗すると、操作全体が拒否されます。これは、すべてが一緒に成功するか、何も進まないことを確認したい場合に役立ちます。
  3. 結合された結果: すべての Promise の結果を一度に必要とする場合 (例: ユーザー データと購入履歴の結合)、Promise.all() は完璧なソリューションです。

例: Promise.all() の使用

const fetchData = async () => {
  const [data1, data2] = await Promise.all([getChart(), getDetails()]);
  console.log('Both requests completed'); // This runs only when both requests finish
};

この例では、getChart() と getDetails() の両方が並行して実行され、関数は両方が終了するまで待機してから先に進みます。 Promise.all() は、両方のリクエストが関連しており、一緒に完了する必要があるこのような状況に最適です。

4. 私の場合 Promise.all() が必要なかった理由

Promise.all() を数回適用した後、コードが常に改善されるわけではないことに気づき始めました。実際、私は物事を複雑にしすぎていました。 getChart() と getDetails() という 2 つの独立した API リクエストがあり、それぞれに独自の読み込みスピナーと結果が含まれていましたが、それらを不必要にバンドルしていました。

Promise.all() を使用すると、リクエストが独立していて相互に依存していないにもかかわらず、コードはどちらかの結果を処理する前に両方のリクエストが完了するまで待機する必要がありました。このような場合、Promise.all() は複雑さを増すだけで実際のメリットはありません。

5. When Promise.all() Might Be Overkill

Sometimes, Promise.all() is overkill. If your async functions are independent, meaning one doesn’t rely on the other to complete, then there’s no need to bundle them together. They can run in parallel just fine without waiting on each other, and you can handle their results independently. This realization hit me when I saw that JavaScript already handles asynchronous tasks efficiently without needing to group everything together.

When to Avoid Promise.all()

  1. Independent Async Functions: If your requests don’t depend on each other, they can complete at different times, and you can handle their results separately. There’s no need to wait for all of them to finish together.
  2. Individual Loading States: In my case, I had individual loading spinners for each request, but I was unnecessarily holding everything up by waiting for both requests. It’s better to handle each request separately and update the UI as soon as each one finishes.

Example: Independent Requests Without Promise.all()

useEffect(() => {
  getChart();   // Trigger first async request
  getDetails(); // Trigger second async request
}, []);

In this setup, both requests run in parallel without needing Promise.all(). You can show individual loading states and handle each result independently, which is exactly what I needed for my project.

6. Real-World Scenarios for Using or Avoiding Promise.all()

Let’s look at how these concepts apply to real-world scenarios.

Scenario 1: Fetching Related Data (Use Promise.all())

Imagine you’re building a dashboard where you need to show user information and user purchase history together. In this case, you’d want to wait for both pieces of information to load before rendering the UI. Here, Promise.all() is the right choice:

const fetchData = async () => {
  const [userInfo, purchaseHistory] = await Promise.all([
    fetchUserInfo(),
    fetchUserPurchaseHistory()
  ]);
  console.log('Both user info and purchase history loaded');
};

Scenario 2: Independent API Calls (Avoid Promise.all())

Now, let’s say you’re fetching chart data and table data for a dashboard, and these two pieces of information are independent of each other. You might want to show a spinner for the chart and a separate one for the table. In this case, there’s no need to wait for both requests to complete together:

useEffect(() => {
  getChart();   // Fire chart request
  getDetails(); // Fire table request
}, []);

Both requests are independent, and you handle each of them separately, updating the UI as soon as each one completes. Promise.all() isn’t necessary here.

Conclusion: Don’t Jump on the Bandwagon

Promise.all() is a powerful tool, but it’s not always the best solution. I jumped on the bandwagon initially, assuming that using it everywhere would make my code better. However, I quickly learned that in cases where async functions are independent and have their own loading states, Promise.all() can actually make things more complicated.

Key Takeaways:

  • Use Promise.all() when you need to wait for multiple promises to resolve before proceeding.
  • Avoid Promise.all() when async tasks are independent, and you can handle them individually without unnecessary waiting.

Ultimately, it’s important to understand when and why to use a feature like Promise.all() instead of just assuming it’s always beneficial. After stepping back and re-evaluating my use case, I found that sticking with independent async calls was the right approach.

以上がPromise.all( ) のジレンマ: それが役に立つときと、それが苦痛になるときの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。