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の中の処理が実行されました。
参考