You can’t cancel a JavaScript promise (except sometimes you can) - JavaScriptのPromiseはキャンセルできない(ただし、場合によってはできる)

動くコードでわかる「awaitをそっと止める」トリック — サーバレスのワークフローで使える中断法

要約

Promiseに標準のキャンセルはないが、「解決しないPromiseで待機を永続化→ガベージコレクタで掃除される」テクニックを使えば、throwも例外処理も使わずにasync関数の途中で実質的に中断(そして再開)できる。

この記事を読むべき理由

サーバレスや短時間実行環境で長時間ワークフローを動かす必要がある場面(日本でも増えるイベント駆動・分散ワークフロー)で、ライブラリやランタイム側がユーザーの普通のasync/awaitコードを壊さずに「中断→保存→再開」する方法を理解できる。

詳細解説

重要コード(抜粋例):

// javascript
async function interrupt() {
  return new Promise(() => { /* 決して解決しない */ });
}

async function execute(fn, stepState) {
  let newStep = null;
  // 実行を開始。ユーザー側は step.run() が新ステップなら永遠に待つ
  fn({
    run: async (id, callback) => {
      if (stepState.has(id)) return stepState.get(id);
      newStep = { id, callback };
      return new Promise(() => { });
    }
  });
  // マクロタスクでマイクロタスク群を枯渇させる
  await new Promise(r => setTimeout(r, 0));
  if (newStep) {
    const result = await newStep.callback();
    stepState.set(newStep.id, result);
    return false; // 未完了(中断した)
  }
  return true; // 完了
}

日本市場との関連性:

実践ポイント

この記事で紹介した手法はランタイム側で透明にワークフロー制御を提供したい場面で強力です。まずは小さなプロトタイプで挙動(イベントループ、GC、例外処理)を確認してください。