ご存知の通り、async/awaitはとても美しく明快であり、JS界隈の誰もが待ち望んだ機能であります。
async function f() {
const x = await g()
}
async/awaitのエラーハンドリングはtry/catchで行うのが一般的です。
しかし、これは複数のawaitを使い、それぞれ別のエラーハンドリングを行いたい場合など、冗長になりがちです。
そして、特に気に入らないのが、tryのスコープ外で非同期関数の戻り値を使う場合、letを使う必要があるところです。
let name = 'ゲスト'
try {
name = awiat getName()
} catch (err) { }
console.log(`ようこそ ${name}さん`)
そこで、await/catchパターンを活用して、これを改善してみましょう。
await/catch パターン
上記をawait/catchパターンで書き換えてみます。
let name = 'ゲスト'
try {
name = awiat getName()
} catch (err) { }
console.log(`ようこそ ${name}さん`)
// => ようこそ ゲストさん
/// ↓ ↓ ↓
const name = await getName().catch(() => 'ゲスト')
console.log(`ようこそ ${name}さん`)
// => ようこそ ゲストさん
グレート!
あの忌々しいletが消え去り、constにより平和が訪れました。ああ、不変性の美しきかな。なにより、ネストが減るのがいいですね。
もう一つパターンを見てみましょう。
複数のasync関数のエラーをそれぞれ別々にハンドリングする必要ある場合です。
try {
await f()
} catch (err) {
handleErr1(err)
}
try {
await g()
} catch (err) {
handleErr2(err)
}
// ↓ ↓ ↓
await f().catch(handleErr1)
await g().catch(handleErr2)
完璧です。
完全に冗長な記述が消え、シンプルなコードになりました。
結局のところ、async関数はPromiseを返す関数でしかなく、awaitはPromiseの解決を待つので、catchをそのまま使えるわけです。
Tips
もちろんawaitとthenを組み合わせることができます。
これは、いちいち変数を用意するまでもない(むしろ冗長な)連続した処理に活用できるでしょう。
const x1 = await func()
const x2 = awiat filter1(x1)
const x3 = await filter2(x2)
// ↓ ↓ ↓
const x = await func().then(filter1).then(filter2)
まとめ
await catchパターンを活用することで、コードが簡潔になることがわかりました。
何かあれば、コメント欄またはツイッターにて議論しましょう。
本記事は、以下からの転載です。