async function case1() {
// ...
const result = await something().catch(err => err)
if (result instanceof Error) {
console.error(result)
if (result.display_message) notifyUser(result.display_message)
return
}
// ...
return result.data
}
async function case2() {
// ...
let result
try {
result = await something()
} catch (err) {
console.error(err)
if (err.display_message) notifyUser(err.display_message)
return
}
// ...
return result.data
}
case2 は見づらいので case1 のほうが好き
速度の違いを調べてみる
async function something(n) {
if (n & 1) throw new Error("error")
return { data: "ok" }
}
async function case1(n) {
const result = await something(n).catch(err => err)
if (result instanceof Error) {
if (result.display_message) notifyUser(result.display_message)
return { ok: false, error: result }
}
return { ok: true, value: result.data }
}
async function case2(n) {
let result
try {
result = await something(n)
} catch (err) {
if (err.display_message) notifyUser(err.display_message)
return { ok: false, error: err }
}
return { ok: true, value: result.data }
}
async function measure1() {
console.time(1)
for (let i = 0; i < 10000; i++) {
await case1(i)
}
console.timeEnd(1)
}
async function measure2() {
console.time(2)
for (let i = 0; i < 10000; i++) {
await case2(i)
}
console.timeEnd(2)
}
!async function () {
await measure1()
await measure2()
await measure1()
await measure2()
await measure1()
await measure2()
await measure1()
await measure2()
}()
1: 258.104736328125ms
2: 198.275146484375ms
1: 252.72900390625ms
2: 210.5810546875ms
1: 286.694091796875ms
2: 210.133056640625ms
1: 262.489990234375ms
2: 220.68994140625ms
2 のほうが微妙に速かった
と言っても倍にもなってないし 1 万回で 40ms 程度の差なので気にせず 1 を使うつもり
ただ今回みたいなケースだと これで十分そう
async function case3(n) {
return something(n).then(
result => ({ ok: true, value: result.data }),
err => {
if (err.display_message) notifyUser(result.display_message)
return ({ ok: false, error: err })
}
)
}
成功時の処理が長いならネストが深くなって見づらくなるので case1 の方法のほうが良さそう
case3 の速度は case1 と case2 の間くらい
自分で catch 書きたくなくて ステータスとして成功・失敗を結果に含んでくれればいいのにと思ってたら最近できた Promise.allSettled がいい感じ
async function case4(n) {
const [result] = await Promise.allSettled([something(n)])
if (result.status === "rejected") {
if (result.reason.display_message) notifyUser(result.reason.display_message)
return { ok: false, error: result.reason }
}
return { ok: true, value: result.value.data }
}
ただ 本来は複数の Promise 全部が成功か失敗で終了したときに resolve される Promise を取得する用途なので配列になる
それでも見た目的にはよさそう
肝心の速度は case1 よりもちょっと遅めだった