6
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?

More than 5 years have passed since last update.

非同期処理の例外処理の書き方

Posted at

promiseとasync awaitの例外処理の書き方を紹介します。

promiseの場合

与えられた引数を2倍にして、コンソールに描画するメソッドを例にして説明します。
2倍にするメソッドとして、doubleメソッドを作ります。
doubleメソッドの引数に10を与えて、console.logを実行すると20が表示されます。

const double = (number) => {
  return new Promise(resolve=>{
    resolve(number * 2)
  })
}

double(10)
  .then(num => console.log(num))
// 実行結果: 20

続けて、doubleメソッドの中で例外を発生させます。

const double = (number) => {
  return new Promise(resolve=>{
    // 意図的に例外を発生
    throw new Error('エラーが発生しました')
    resolve(number * 2)
  })
}

double(10)
  .then(num => console.log(num))
// 何も表示されない

例外が発生した時に、受け取る処理を書かないと何も表示されません。
これでは、システム内でエラーが発生しても何も通知されないことになります。

では、例外処理を書いていきます。
promiseオブジェクトはcatchメソッドが使えるので、thenに続けてcatchを記述します。

const double = (number) => {
  return new Promise(resolve=>{
    // 意図的に例外を発生
    throw new Error('エラーが発生しました')
    resolve(number * 2)
  })
}

double(10)
  .then(num => console.log(num))
  .catch(error => {
    // 例外が発生するとcatchに入る
    console.log(error.message)
  })
// 実行結果: エラーが発生しました

doubleメソッド内でエラーが発生した時にthenメソッドを飛ばしてcatchメソッドに処理が移行します。
catchメソッド内でerror.messageと記述すると、new Errorで設定した「エラーが発生しました」というメッセージを表示するとことができます。

ちなみに、thenとcatchがチェーンになっている場合、以下のような動きになります。

const printA = () => {
  console.log('A')
}
const printB = () => {
  console.log('B')
}
const printC = () => {
  console.log('C')
}
const rejected(){
  console.log('reject')
}

// パターンA
Promise.resolve()
  .then(printA)
  .then(printB)
  .catch(rejected)
  .then(printC)

// 実行結果
// A
// B
// C

// パターンB
Promise.reject()
    .then(printA)
    .then(printB)
    .catch(rejected)
    .then(printC)

// 実行結果
// reject
// C

パターンA:
例外が発生しなかった場合、catchメソッドは実行されずに次のthenメソッドまで処理が移行します。

パターンB:
例外が発生した場合、catchメソッドまで処理が移行した後、thenメソッドが実行されます。

async awaitの場合

promiseの時と同じく、与えられた引数を2倍にして、コンソールに描画するメソッドを例にして説明します。

const double = async (number) => {
  return (number * 2)
}

const exec = async () => {
  const result = await double(10)
  console.log(result)
}

exec()
// 実行結果: 20

正常に結果が返り、20と表示されました。
続いて、例外処理を書いていきます。
async awaitの場合はtry-catch文を使います。

const double = async (number) => {
  throw new Error('エラーが発生しました')
  return (number * 2)
}

const exec = async () => {
  try {
    const result = await double(10)
    console.log(result)
  } catch (e) {
    console.log(e.message)
  }
}

exec()
// 実行結果: エラーが発生しました

例外が発生して、catch文に処理が移行したことを確認できました。

まとめ

システムにエラーは付きもので、エラーが起きた時にcatchする機能がないとユーザには何も通知されずに利便性の悪いものになってしまいます。
なので、適切な場所に例外処理を記述することをお勧めします。

おまけ

try-catch文の中で、promiseのcatchを書くとどうなるでしょう?
やってみましょう。

const double = number => {
  return new Promise(resolve=>{
    // 意図的に例外を発生
    throw new Error('エラーが発生しました')
    resolve(number * 2)
  })
}

try {
  double(10)
    .then(num => console.log(num))
    .catch(error => {
      // promiseのcatch処理
      console.log('promiseのcatch処理')
  })
} catch {
  // try-catchのcatch処理
  console.log('try-catch文のcatch処理')
}
// 実行結果: promiseのcatch処理

結果より、try-catch文のcatchには入らずに、promiseのcatchの中の処理が実行されました。

参考

6
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
6
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?