Javascript

Promise の基本と実務活用ガイド – then・catch・all から async/await まで

ⓘ本ページはプロモーションが含まれています

もっとスキルを活かしたいエンジニアへ

スポンサードリンク
働き方から選べる

無料で使えて良質な案件の情報収集ができるサービス

エンジニアの世界では、「いつでも動ける状態を作っておけ」とよく言われます。
技術やポートフォリオがあっても、自分に合う案件情報を日常的に見れていないと、いざ動こうと思った時に比較や判断が難しくなってしまいます。
普段から案件情報が集まる環境を作っておくと、良い案件が出た時にすぐ動きやすくなりますよ。
筆者自身も、メガベンチャー勤務時代に年収1,500万円を超えた経験があります。振り返ると、技術だけでなく「どんな案件や働き方があるか」を日頃から見ていたことが、キャリアの選択肢を広げるきっかけになりました。
このブログを読んでくれた方に感謝を込めて、実際に使っている情報収集サービスを紹介します。

フルリモート・週3日・高単価、どんな条件も妥協したくないなら

フリーランスボードに無料会員登録する

利用者10万人以上。業界最大規模45万件の案件。AIマッチ機能や無料の相場情報が人気。

年収800万円以上のキャリアアップ・ハイクラス正社員を視野に入れているなら

Beyond Careerに無料相談する

内定獲得率90%以上。紹介先企業とは役員クラスのコネクションがある安心と信頼できるエージェント。


スポンサードリンク

Promise の基本概念と主要 API

Promise は「将来的に値が返ってくる」ことを約束したオブジェクトで、非同期処理の結果を統一的に扱えるように設計されています。
本セクションでは 状態遷移主要メソッド(then / catch / finally) の挙動を整理し、実務で正しく使うためのポイントを解説します。

状態(pending・fulfilled・rejected)とライフサイクル

Promise は生成直後は pending です。
- resolve(value) が呼ばれると fulfilled に遷移し、value が結果として渡されます。
- reject(reason) が呼ばれると rejected に遷移し、reason がエラー情報になります。

状態は一度決まると変更できません(イミュータブル)。この不変性が チェーン可能 な理由です。

詳細は Zenn の解説を参照 → https://zenn.dev/divsawa/articles/20260201_js-promise-async-await
※外部リンクは定期的に有効性(200 OK)を確認し、アクセス不能になった場合は代替 URL に差し替えてください。

then / catch / finally の使い方と戻り値

then(onFulfilled, onRejected)fulfilled 時に onFulfilledrejected 時に onRejected を呼び出します。
catch(onRejected)then(undefined, onRejected) と同等で、エラーハンドリングをシンプルに記述できます。

重要なのは then が返すのは新しい Promise である点です。これにより次のような直列チェーンが可能になります。

finally(callback) は結果に関係なく必ず実行され、返す Promise は前段の状態(fulfilled / rejected)をそのまま受け継ぎます。

Qiita の図解解説 → https://qiita.com/ktdatascience/items/801b039d6438160edc4f
※リンク切れリスクに備えて、定期的にアクセス確認ツール(例: curl -I)でステータスコードをチェックしてください。


new Promise での手動実装と直列チェーン

この章ではコールバック API を Promise に変換 するパターンと、エラーハンドリングを強化した 直列処理のベストプラクティスを紹介します。

new Promise の構文と resolve / reject の実例(タイマーラッパーなど)

まずは setTimeout を Promise で包むシンプルな例です。エラー発生時に明示的に reject することで、呼び出し側で統一的に捕捉できます。

次に Node.js のコア API fs.readFile を Promise 化した例です。エラーは必ず reject に流すため、呼び出し側で try / catch が機能します。

Promise チェーンによる直列処理とエラーハンドリングのベストプラクティス

以下は delay → ファイル読み込み → JSON パース を順に行う例です。各 then が新しい Promise を返すので、途中で例外が起きても最終的な catch で一括捕捉できます。

同様の直列例は Qiita に掲載 → https://qiita.com/ktdatascience/items/2fc46c542355067e100a
※リンクの有効性は半年ごとに自動スクリプトでチェックし、404 が返ったら別記事へ差し替える運用を推奨します。


複数の Promise を同時制御するメソッドと実務活用例

ここでは 並列処理 に適した組み込みメソッド(Promise.all, allSettled, race, any)の特徴と、実際にプロジェクトで採用すべきシナリオを解説します。

Promise.all と allSettled の違いと使い分け(並行 API 呼び出し)

Promise.all(iterable)全てが fulfilled した場合のみ結果配列を返し、1 つでも rejected があれば即座にエラーとなります。大量リクエストの トランザクション的 な処理に向きます。

対照的に Promise.allSettled は各 Promise の 成功/失敗ステータス をすべて取得でき、部分的に結果を利用したいダッシュボード等で有用です。

実務では「全体成功が前提のバッチ処理」→all、「一部だけでも表示したい UI」→allSettled を選択します。

Promise.race と any の特徴とユースケース(タイムアウト・最速レスポンス取得)

Promise.race(iterable)最初に決定された(fulfilled か rejected)Promise をそのまま返すため、タイムアウト実装や「最速の API」取得に適しています。

Promise.any(iterable)最初に fulfilled したものだけを返し、すべてが rejected の場合のみ AggregateError をスローします。フォールバック先が複数ある場合の「どれか一つ成功すれば良い」シナリオで便利です。

メソッド比較は codingls.com のまとめが参考 → https://codingls.com/js/6189/
※外部リンクは CI パイプラインで HEAD リクエストを走らせ、200 系ステータス以外の場合は Slack に通知する仕組みを導入すると運用が楽です。


async/await との比較・変換テクニック

Promise ベースのコードを async/await に置き換えると可読性が向上しますが、例外処理や finally の扱いに注意が必要です。本節では変換手順と実務で気をつけるポイントを示します。

Promise ベースのコードを async/await に置き換える例

先ほどの直列チェーンを async 関数へリファクタリングした完全版です。エラーハンドリングは try / catch で包括的に行い、finally は必ず実行されます。

変換のポイント

Promise async/await
then await
catch try / catch
finally 同名の finally ブロック

同期風に書くテクニックと注意点(エラーハンドリング、finally の扱い)

  • 必ず try/catchawait が reject された場合は例外としてスローされるため、忘れずに捕捉します。
  • finally は必ず実行returnthrow があっても finally 内のコードは走りますが、return の結果は上書きできません(注意)。
  • 配列を順次処理したいときは for await…of:並列にしたくない場合はループ内で await を使うだけで安全です。

「同期的に制御したい」解説は watashi.xyz に詳述 → https://watashi.xyz/js-promise/
※リンク先が将来的に消失しないよう、GitHub のミラーリポジトリや自前のドキュメントへも同内容を保存しておくと安全です。


実務で役立つ高度な実装例とデバッグ手法

この章では fetch に対するリトライ・タイムアウト・キャンセル、汎用的な Promise ラッパー、そして開発時に便利なデバッグテクニックを紹介します。

fetch と組み合わせたリトライ・タイムアウト・キャンセル(AbortController)

以下のユーティリティは 最大 3 回までリトライ5 秒のタイムアウト、そして外部からの AbortController によるキャンセルに対応しています。エラーハンドリングを細かく分岐させている点が実務向きです。

使用例(キャンセルボタン付き UI)

カスタムユーティティティとしての Promise ラッパー

ファイル読み込みシミュレーション(テスト用モック)

データベースクエリラッパー(Node の pg ライブラリ想定)

デバッグテクニック:console.time、async stack trace の取得、VSCode デバッガ活用

手法 効果 使用例
console.time / console.timeEnd 非同期ブロックの実行時間を測定でき、パフォーマンスボトルネックを可視化 js\nconsole.time('api');\nawait fetch('/slow');\nconsole.timeEnd('api');\n
Async Stack Trace エラー発生箇所を非同期チェーン全体で追跡でき、原因特定が容易になる js\nError.stackTraceLimit = 50; // デフォルトは10\nthrow new Error('test');\n
VSCode の「Async Call Stacks」デバッグ ブレークポイントで Promise の内部状態や呼び出し元を確認でき、ステップ実行が快適になる launch.json"runtimeArgs": ["--inspect-brk"] を設定し、VSCode から起動

詳細は codingls.com の実務パターン解説ページが参考になります → https://codingls.com/js/6189/


まとめと次のアクション

  • Promise の基本:状態遷移は一方向で不変、then / catch / finally がチェーンを可能にします。
  • 手動実装new Promise で既存コールバック API を包み、エラーハンドリングは必ず reject に流す設計が重要です。
  • 同時制御Promise.all / allSettled は全体成功と部分結果取得の使い分け、race / any はタイムアウトや最速応答取得に活用します。
  • async/await への移行try / catch / finally に置き換えるだけで可読性が向上し、エラーは一元管理できます。
  • 高度実装例:リトライ・タイムアウト・AbortController を組み合わせた fetchWithRetry、汎用的な DB/ファイルラッパー、そして console.time や VSCode デバッガによるデバッグ手法で信頼性を高めます。

実務導入のチェックリスト
1. すべての外部リンクは CI パイプラインで定期的にステータスコードを検証する。
2. Promise ラッパーは必ず reject にエラーオブジェクト(Error 派生)を渡し、呼び出し側で catch できるようにする。
3. エラーハンドリングが簡素化されていないかコードレビュー時に確認し、必要なら詳細例外情報を付与する。

これらのパターンを自プロジェクトに組み込めば、非同期ロジックの可読性・保守性・信頼性が格段に向上します。ぜひ本稿で紹介したコードスニペットをベースに、実際の開発フローへすぐに適用してみてください。

スポンサードリンク

もっとスキルを活かしたいエンジニアへ

スポンサードリンク
働き方から選べる

無料で使えて良質な案件の情報収集ができるサービス

エンジニアの世界では、「いつでも動ける状態を作っておけ」とよく言われます。
技術やポートフォリオがあっても、自分に合う案件情報を日常的に見れていないと、いざ動こうと思った時に比較や判断が難しくなってしまいます。
普段から案件情報が集まる環境を作っておくと、良い案件が出た時にすぐ動きやすくなりますよ。
筆者自身も、メガベンチャー勤務時代に年収1,500万円を超えた経験があります。振り返ると、技術だけでなく「どんな案件や働き方があるか」を日頃から見ていたことが、キャリアの選択肢を広げるきっかけになりました。
このブログを読んでくれた方に感謝を込めて、実際に使っている情報収集サービスを紹介します。

フルリモート・週3日・高単価、どんな条件も妥協したくないなら

フリーランスボードに無料会員登録する

利用者10万人以上。業界最大規模45万件の案件。AIマッチ機能や無料の相場情報が人気。

年収800万円以上のキャリアアップ・ハイクラス正社員を視野に入れているなら

Beyond Careerに無料相談する

内定獲得率90%以上。紹介先企業とは役員クラスのコネクションがある安心と信頼できるエージェント。


-Javascript