1. minodisk

    Posted

    minodisk
Changes in title
+Promiseでalwaysする方法
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,121 @@
+簡単で、`catch`以降に処理を書くとエラー発生の有無に関わらず実行される。[jsbin](https://jsbin.com/kosutu/edit?js,console)
+
+```js
+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](https://jsbin.com/miyelul/edit?js,console)
+
+```js
+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](https://jsbin.com/qoyifu/edit?js,console)
+
+```js
+const example = () => {
+ let error
+ const p = Promise.resolve()
+ .then(() => console.log('ゴミが発生'))
+ .then(() => 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](https://jsbin.com/viteha/edit?js,console)
+
+```js
+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](https://jsbin.com/qunave/edit?js,console)
+
+```js
+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](https://jsbin.com/kutigu/edit?js,console)
+
+```js
+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)) // 実行されない
+```