2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptにおける非同期設計戦略:Promise / async/await / 並列処理とエラーフロー設計

Posted at

概要

非同期とは「後で起こる」ではなく、
「制御の流れが分断される構造」そのものである。

現代のJavaScriptアプリケーションにおいて、非同期処理は通信・IO・遅延処理など、あらゆるUXのコアとして存在する。
しかし、設計を誤ればそれはバグの温床・読みづらさ・失敗時の不安定な状態を生む。

本稿では、非同期制御の戦略的設計:Promise / async/await の原則、並列 vs 逐次制御、タイムアウト・キャンセル・エラーフローの構造化を包括的に整理する。


1. Promiseの原則と構造

const fetchUser = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve({ name: 'Toto' }), 1000);
  });
  • ✅ resolve / reject は一度だけ
  • ✅ 状態:pending → fulfilled / rejected
  • .then().catch().finally() でチェーン制御

2. async/await構文:非同期を同期的に書く

async function loadUser() {
  try {
    const user = await fetchUser();
    console.log(user.name);
  } catch (e) {
    console.error('取得失敗:', e);
  }
}
  • awaitPromiseを待つ
  • try/catch により同期的なエラーフロー設計が可能
  • await の連発は逐次処理による性能劣化に注意

3. 並列処理 vs 逐次処理の設計判断

❌ 逐次処理:時間がかかる

const a = await fetchA();
const b = await fetchB();

✅ 並列処理:同時に開始

const [a, b] = await Promise.all([fetchA(), fetchB()]);

→ ✅ 依存がなければ並列に、依存があるなら逐次に切り分けて設計


4. タイムアウト・キャンセル設計

function withTimeout(promise, ms) {
  const timeout = new Promise((_, reject) =>
    setTimeout(() => reject(new Error('Timeout')), ms)
  );
  return Promise.race([promise, timeout]);
}
  • ✅ ネットワーク遅延・API停止時のUIロック防止
  • ✅ AbortController との併用で実際の通信も中断可能

5. エラーフローの一貫性とUI統合戦略

async function submit() {
  try {
    showLoading();
    const res = await sendData();
    showSuccess();
  } catch (e) {
    showError('送信に失敗しました');
  } finally {
    hideLoading();
  }
}
  • ✅ ロジックとUIをイベント的に接続
  • finally共通終了処理を保証

6. 複数Promiseの制御構造

const results = await Promise.allSettled([
  fetchA(),
  fetchB(),
  fetchC(),
]);
  • Promise.all → いずれか失敗で即reject
  • Promise.allSettled全ての成功/失敗を把握可能
  • Promise.any → 最初に成功したものを返す(他は無視)

→ ✅ 目的に応じて制御構造を設計的に選択する


設計判断フロー

① Promiseとasync/awaitを混在していないか? → await優先で構造統一

② 処理が依存してるか? → 逐次か並列かで設計を明確化

③ 失敗時のUI制御はどうなっているか? → try/catch/finallyを必ず設計

④ API遅延に備えているか? → withTimeout / AbortControllerを検討

⑤ 複数非同期の制御方針はあるか? → all / allSettled / any の選定を戦略的に

よくあるミスと対策

❌ 複数 await を連続で書き、パフォーマンスが悪化

→ ✅ 依存がなければ Promise.all() で並列化


❌ API失敗時に何も表示されない

→ ✅ catchブロック内でUIに対して明示的通知を設計


❌ async関数内でエラーを無視してクラッシュ

→ ✅ try/catch常にロジックの中で明示的に設計する


結語

非同期とは「ただ待つ」ことではない。
それは**“制御の流れが見えない世界”を“構造的に可視化する”ための設計行為**である。

  • 流れを明確にし
  • 失敗を想定し
  • 同時性を設計し
  • UIとの整合を保証する

JavaScriptにおける非同期設計とは、
「後で何が起こるか」を未来の自分に説明できる構造である。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?