Promiseとasync/awaitはどちらか一方しか使わないと誤解していました。
そこで、組み合わせの方法と使い分けの基準を整理しました。
1. よくある誤解
| 誤解 | 実際 |
|---|---|
| Promiseとasync/awaitはどちらか一方を使う |
async/awaitはPromiseを読みやすくした書き方。併用できる |
| Promiseチェーンは古い | 今でも関数的な処理や動的な直列制御で有効 |
| async/awaitですべて対応できる | 処理の内容によってはPromiseチェーンの方が適する場面もある |
2. 単体での使い分け表
| 判断基準 | 向いている書き方 | 理由 |
|---|---|---|
| 長い手順で流れを明確にしたい | async/await | 順次処理が上から下に読みやすい/エラーをtry-catchで一括管理可能 |
| 小さな処理を関数的につなぎたい | Promiseチェーン |
.then()で宣言的にパイプ構築できる |
| forEachなどで順次処理したい | Promiseチェーン | 動的な直列処理が組みやすい |
| ライブラリがPromiseを返す | どちらでも可 |
.then()でもawaitでも受けられる |
3. 組み合わせパターン
3-1. async関数の中にPromiseチェーンを使う
async function fetchAndRender() {
const items = await fetch(url)
.then(r => r.json())
.then(json => json.items);
render(items);
}
ポイント:awaitはチェーン全体の完了を待つ。
この書き方のメリットについては、以下の記事で詳しく解説しています:
なぜ async/await で Promise チェーン全体をまとめるのか?
3-2. Promiseを返すユーティリティ関数をawaitで使う
function compressFile(file) {
return new Promise((resolve, reject) => { /* 処理 */ });
}
async function handleUpload(file) {
const zipped = await compressFile(file);
await upload(zipped);
}
ポイント:既存のPromise関数はそのままawaitで待てる。
3-3. ループで順次処理(動的な直列処理)
let chain = Promise.resolve();
urls.forEach(url => {
chain = chain.then(() => fetch(url));
});
await chain;
ポイント:Promiseチェーンで構築 → 最後にawaitで待機。
4. まとめ
-
async/awaitはPromiseを読みやすくした書き方であり、内部動作は同じ。 - 現場では単体ではなく併用されることが一般的。
- 処理の「流れの読みやすさ」「動的構築の必要性」「エラー管理の範囲」に応じて使い分けるとよい。