Edited at

Promiseでalwaysする方法

More than 3 years have passed since last update.

簡単で、catch以降に処理を書くとエラー発生の有無に関わらず実行される。jsbin

Promise.resolve()

.then(() => console.log('通常時: 1'))
.catch(err => {})
.then(() => console.log('通常時: 2'))

// -> 通常時: 1
// 通常時: 2

Promise.reject(new Error())
.then(() => console.log('エラー時: 実行されない'))
.catch(err => {})
.then(() => console.log('エラー時: 1'))

// -> エラー時: 1


どのようなケースで使うか

あるスコープで発生したゴミをそのスコープ内で掃除したいというケースなどに有用。jsbin

const example = () => {

const p = Promise.resolve()
.then(() => console.log('ゴミが発生'))
.then(() => {
console.log('エラーが発生')
return Promise.reject(new Error)
})
.then(() => console.log('通常なら実行される')) // スキップされる
.catch(err => {})
.then(() => console.log('ゴミを処理')) // エラーの有無にかかわらず実行される
return p
}

example()


捕捉したエラーを変数に確保し、共通処理後にリジェクトするパターン

example()の呼び出し元でエラーハンドリングを行いたいことがある。

スコープ内でcatchしたエラーを共通処理後にもう一度rejectしてあげると、以降のthenはスキップされ次に現れるcatchでエラーを捕捉できる。jsbin

const example = () => {

let error
const p = Promise.resolve()
.then(() => console.log('ゴミが発生'))
.then(() => {
console.log('エラーが発生')
return Promise.reject(new Error)
})
.then(() => console.log('通常なら実行される')) // スキップされる
.catch(err => error = err) // キャッチしたエラーを変数に格納
.then(() => {
console.log('ゴミを処理') // エラーの有無にかかわらず実行される
if (error) {
return Promise.reject(error) // エラーがある場合はrejectする
}
})
return p // Promiseインスタンスを返却
}

example()
.then(() => console.log('exampleが通常なら実行される')) // スキップされる
.catch((err) => console.log('exampleがエラーなら実行される')) // 実行される


捕捉したエラーを共有処理に渡し、共通処理後にリジェクトするパターン

次のように、catchで捕捉したエラーをreturnし、次のthenに渡すというエラーを変数に確保しないパターンもある。jsbin

const example = () => {

return Promise.reject(new Error())
.catch(err => err)
.then((err) => {
if (err) {
return Promise.reject(err)
}
})
}

example()
.catch((err) => console.log(err)) // 実行される

一時確保用の余計な変数がなくなって良さそうに見えるけど、catch前のチェーンで何かを渡している場合は、エラーが起こらないとcatch後のthenにその値が渡ってしまい、エラーではないのにrejectしてしまう。jsbin

const example = () => {

return Promise.resolve('エラーではない何か')
.catch(err => err)
.then((err) => {
console.log(err) // -> 'エラーではない何か'
if (err) {
return Promise.reject(err)
}
})
}

example()
.catch((err) => console.log(err)) // -> 'エラーではない何か'

これは意図しない挙動で、catch後のthenに渡ってくる引数がエラーなのかを判定しなければならない。jsbin

const example = () => {

return Promise.resolve('エラーではない何か')
.catch(err => err)
.then((arg) => {
console.log(arg) // -> 'エラーではない何か'
if (arg instanceof Error) {
return Promise.reject(arg)
}
})
}

example()
.catch((err) => console.log(err)) // 実行されない