javascriptの非同期処理で、一旦別のメソッドにてエラーレスポンスを受け取った後に、続けて呼び出し元にエラーレスポンスとして返却したいといった時があり、Promise
とawait/catch
の仕様を改めて振り返ってみたのでメモとして記事にします。
Promiseを使用する方法
処理の流れ
rejectPromiseFunc()
でrejected状態のPromiseエラーを返すpromiseFunc1
のcatch()でエラーを受け取り、再度rejected状態にしたPromiseエラーを返すpromiseFunc2
のcatch()も2.と同様- 呼び出し元のcatch()で、
rejectPromiseFunc()
で発生したエラーを受け取ることができる
function rejectPromiseFunc() {
console.log("===> Call rejectPromiseFunc")
return new Promise((resolve, reject) => {
const error = new Error("エラーが発生しました")
setTimeout(() => {
reject(error)
}, 500);
})
}
function promiseFunc1() {
console.log("promiseFunc1")
return new Promise((resolve, reject) => {
rejectPromiseFunc()
.then(response => {
console.log("then[1]: " + response)
resolve(response)
})
.catch(error => {
console.log("catch[1]: " + error)
reject(error)
})
})
}
function promiseFunc2() {
console.log("promiseFunc2")
return new Promise((resolve, reject) => {
promiseFunc1()
.then(response => {
console.log("then[2]: " + response)
resolve(response)
})
.catch(error => {
console.log("catch[2]: " + error)
reject(error)
})
})
}
promiseFunc2()
.then(response => {
console.log("then[3]: " + response)
})
.catch(error => {
console.log("catch[3]: " + error)
})
実行結果
promiseFunc2
promiseFunc1
===> Call rejectPromiseFunc
catch[1]: Error: エラーが発生しました
catch[2]: Error: エラーが発生しました
catch[3]: Error: エラーが発生しました
async functionを使用する方法
async functionについて
- async functionは呼び出されるとPromiseを返す
- async functionが値をreturnした場合、Promiseは戻り値をresolveする
- async functionが例外や何らかの値をthrowした場合はその値をrejectする
処理の流れ
rejectPromiseFunc()
でrejected状態のPromiseエラーを返すasyncFunc1
のcatch()でエラーを受け取り、throw
により例外を作り出し、再度rejected状態にしたPromiseエラーを返すasyncFunc2
のcatch()も2.と同様- 呼び出し元のcatch()で、
rejectPromiseFunc()
で発生したエラーを受け取ることができる
function rejectPromiseFunc() {
console.log("===> Call rejectAsyncFunc");
const error = new Error("エラーが発生しました")
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(error)
}, 500);
})
}
async function asyncFunc1() {
console.log("asyncFunc1")
const result = await rejectAsyncFunc()
.catch(error => {
console.log("await/catch[1]: " + error)
throw error
})
console.log("async/success[1]: " + result)
return result
}
async function asyncFunc2() {
console.log("asyncFunc2")
const result = await asyncFunc1()
.catch(error => {
console.log("await/catch[2]: " + error)
throw error
})
console.log("async/await[2]: " + result)
return result
}
asyncFunc2()
.then(response => {
console.log("then: " + response)
})
.catch(error => {
console.log("catch: " + error)
})
実行結果
asyncFunc2
asyncFunc1
===> Call rejectAsyncFunc
await/catch[1]: Error: エラーが発生しました
await/catch[2]: Error: エラーが発生しました
catch: Error: エラーが発生しました
実際に使用したパターン
axiosなどのAPIクライアントでエラーレスポンスを共通処理としてハンドルする時に使用しました。
axios.interceptors.response.use(
response => {
return Promise.resolve(response)
},
error => {
const errorResponse = error.response
if (errorResponse && errorResponse.data && errorResponse.data.hoge_flg) {
// アプリケーション共通で行いたいエラーハンドリング
const msg = errorResponse.data.error
notification(msg)
location.href = `/hogehoge`
return
}
// コンポーネント側でエラーハンドリングを行う
return Promise.reject(error)
}
)