1. minodisk

    No comment

    minodisk
Changes in body
Source | HTML | Preview

簡単で、catch以降に処理を書くとエラー発生の有無に関わらず実行される。jsbin

Promise.resolve()
  .then(() => console.log('通常時: 1'))
  .catch(err => {})
  .then(() => console.log('通常時: 2'))

// -> 通常時: 1
//    通常時: 2

Promise.reject(new Error())
  .then(() => console.log('エラー時: 実行されない'))
  .catch(err => {})
  .then(() => console.log('エラー時: 1'))

// -> エラー時: 1

どのようなケースで使うか

あるスコープで発生したゴミをそのスコープ内で掃除したいというケースなどに有用。jsbin

const example = () => {
  const p = Promise.resolve()
    .then(() => console.log('ゴミが発生'))
    .then(() => {
      console.log('エラーが発生')
      return Promise.reject(new Error)
    })
    .then(() => console.log('通常なら実行される'))  // スキップされる
    .catch(err => {})
    .then(() => console.log('ゴミを処理'))          // エラーの有無にかかわらず実行される
  return p
}

example()

捕捉したエラーを変数に確保し、共通処理後にリジェクトするパターン

example()の呼び出し元でエラーハンドリングを行いたいことがある。
スコープ内でcatchしたエラーを共通処理後にもう一度rejectしてあげると、以降のthenはスキップされ次に現れるcatchでエラーを捕捉できる。jsbin

const example = () => {
  let error
  const p = Promise.resolve()
    .then(() => console.log('ゴミが発生'))
    .then(() => Promise.reject(new Error))          // エラーが発生
    .then(() => console.log('通常なら実行される'))  // スキップされる
    .catch(err => error = err)                      // キャッチしたエラーを変数に格納
    .then(() => {
      console.log('ゴミを処理')                     // エラーの有無にかかわらず実行される
      if (error) {
        return Promise.reject(error)                // エラーがある場合はrejectする
      }
    })
  return p                                          // Promiseインスタンスを返却
}

example()
  .then(() => console.log('exampleが通常なら実行される'))       // スキップされる
  .catch((err) => console.log('exampleがエラーなら実行される')) // 実行される
const example = () => {
  let error
  const p = Promise.resolve()
    .then(() => console.log('ゴミが発生'))
    .then(() => {
      console.log('エラーが発生')
      return Promise.reject(new Error)
    })
    .then(() => console.log('通常なら実行される'))  // スキップされる
    .catch(err => error = err)                      // キャッチしたエラーを変数に格納
    .then(() => {
      console.log('ゴミを処理')                     // エラーの有無にかかわらず実行される
      if (error) {
        return Promise.reject(error)                // エラーがある場合はrejectする
      }
    })
  return p                                          // Promiseインスタンスを返却
}

example()
  .then(() => console.log('exampleが通常なら実行される'))       // スキップされる
  .catch((err) => console.log('exampleがエラーなら実行される')) // 実行される

捕捉したエラーを共有処理に渡し、共通処理後にリジェクトするパターン

次のように、catchで捕捉したエラーをreturnし、次のthenに渡すというエラーを変数に確保しないパターンもある。jsbin

const example = () => {
  return Promise.reject(new Error())
    .catch(err => err)
    .then((err) => {
      if (err) {
        return Promise.reject(err)
      }
    })
}

example()
  .catch((err) => console.log(err)) // 実行される

一時確保用の余計な変数がなくなって良さそうに見えるけど、catch前のチェーンで何かを渡している場合は、エラーが起こらないとcatch後のthenにその値が渡ってしまい、エラーではないのにrejectしてしまう。jsbin

const example = () => {
  return Promise.resolve('エラーではない何か')
    .catch(err => err)
    .then((err) => {
      console.log(err)              // -> 'エラーではない何か'
      if (err) {
        return Promise.reject(err)
      }
    })
}

example()
  .catch((err) => console.log(err)) // -> 'エラーではない何か'

これは意図しない挙動で、catch後のthenに渡ってくる引数がエラーなのかを判定しなければならない。jsbin

const example = () => {
  return Promise.resolve('エラーではない何か')
    .catch(err => err)
    .then((arg) => {
      console.log(arg)              // -> 'エラーではない何か'
      if (arg instanceof Error) {
        return Promise.reject(arg)
      }
    })
}

example()
  .catch((err) => console.log(err)) // 実行されない