Skip to content
Latchkey

Promise とは?未来の値のためのプレースホルダ

promise は、まだ準備できていない値の代わりとなるオブジェクトで、非同期操作の最終的な成功または失敗を表します。

promise(一部の言語では future と呼ばれます)は、後で存在する結果へのハンドルです。呼び出す callback を渡す代わりに、async 関数はただちに promise を返します。成功したときと失敗したときのハンドラを取り付けると、操作が完了した時点で promise がそれらに通知します。promise はきれいに連鎖し、async/await を支えます。

promise の状態

promise は操作が終わるまで pending で、その後、値とともに fulfilled になるかエラーとともに rejected になります。いったん settle すると、その状態は決して変わりません。then と catch で取り付けたハンドラは promise が settle したときに実行され、それがすでに起きていても実行されます。

なぜ promise は生の callback に勝るのか

  • ネストする代わりに then で連鎖し、非同期のフローを平坦化します。
  • エラーは連鎖を下って 1 つの catch まで伝播します。
  • 合成できます。組み込みのヘルパーで、すべてを待ったり、複数を race させたりします。
  • async/await が作られている基礎です。

promise と async/await

async/await は promise の糖衣です。async 関数は promise を返し、await は promise が settle するまで一時停止し、その値を返すかエラーを throw します。promise を理解することは、async/await が内部で何をするかを理解することです。

promise のよくある間違い

連鎖から promise を return しないと順序が壊れます。catch を忘れると reject が未処理のままになります。promise を作っても await しないと、その作業とエラーが黙って失われます。微妙なバグの頻繁な源です。

簡単な例

fetch(url).then(res => res.json()).catch(err => report(err)) を呼ぶと promise を返し、レスポンスが届いたときにそれをパースし、あらゆる失敗を 1 つの error handler へ回します。

CI における promise

未処理の promise の reject や await されない promise は、負荷のかかった runner で現れては消える、順序依存で flaky なテストの失敗を招きます。Latchkey は未処理の reject を追い詰める間、一時的な失敗を自動 retry できるため、1 回の間欠的な失敗が pipeline をブロックしません。

重要なポイント

  • promise は、結果で fulfill するかエラーで reject する未来の値を表します。
  • promise は連鎖・合成でき、生の callback のネストとエラー処理を修正します。
  • async/await は promise の上に作られています。未処理の reject は flaky なテストを招きます。

関連ガイド