JavaScriptにおけるプロミスチェーンの例外処理

何らかの理由で私たちのプロミスが エラーで終了するとします:

javascriptlet promise = new Promise(function(resolve, reject) {
  setTimeout(function() {
    reject('error');
  }, 3000);
});

この場合、コードの実行は即座に、 エラーハンドラー関数を持つ then、 または最初に現れる catchのいずれかに 移ります(どちらが先かによります)。

最初の状況の例は以下の通りです:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    return result + '2';
  },
  function(error) {
    // 実行はここに直ちにジャンプする
  }
).then(
  function(result) {
    console.log(result);
  }
);

二つ目の状況の例は以下の通りです:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    return result + '2';
  }
).catch(
  function(error) {
    // 実行はここに直ちにジャンプする
  }
).then(
  function(result) {
    console.log(result);
  }
);

ハンドラー関数には2つの行動の選択肢があります: 例外的な状況に対処できた場合は、 return を通じて結果を返し、 実行はチェーンに沿って続行されます。 エラーに対処できなかった場合は、 何も返さないか、または throw を通じて例外をスローすることができます。 この場合、実行は次のエラーキャッチャー (次に現れる then または catch) に移ります。

原則として、チェーン内のすべてのエラーは 一箇所で捕捉されます: チェーンの終端に catch を配置します:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    return result + '2';
  }
).catch(
  function(error) {
    // エラー発生時にここに入る
  }
);

例外はプロミス自体で発生する可能性があるほか、 チェーンのどのリンクでも throw によってスローされる可能性があります:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    if (allGood) {
      return result + '2';
    } else {
      throw new Error('エラー'); // 最も近いキャッチャーにジャンプ
    }
  }
)
.then(
  function(result) {
    return result + '3';
  }
).catch(
  function(error) {
    // 最も近いキャッチャー
  }
);

catch は、まさにエラーの診断のために 必要であることに留意してください: エラーが 解決可能か否か。エラーが解決可能である場合、 catch はその解決策を自身に続く then に渡すべきです。 解決不可能な場合(またはこの catch が その解決方法を知らない場合)、私たちは 何も返さないか、または例外をスローすべきです:

javascriptpromise.then(
  function(result) {
    return result + '1';
  }
).then(
  function(result) {
    return result + '2';
  }
).catch(
  function(error) {
    if (errorSolvable) {
      return 'data'; // 次の then へ送る
    } else {
      // 何も返さないか、例外をスローする
    }
  }
).then(
  function(result) {
    // ここでエラーを解決する
  }
);