|
| 1 | +## Nuxt.jsでAPIエラーをどう扱うか |
| 2 | + |
| 3 | +[ビュー - Nuxt.js](https://ja.nuxtjs.org/guide/views/#%E3%82%A8%E3%83%A9%E3%83%BC%E3%83%9A%E3%83%BC%E3%82%B8) |
| 4 | + |
| 5 | +Nuxt.js は `axios で ajax をすることが主流` になりますが、その場合のエラーハンドリングはなかなか悩ましいものです。 |
| 6 | + |
| 7 | +とくに、共通的な処理を実装するのか、そのまま使うのかなど、考え出すと定石を見つけるのは難しいです。 |
| 8 | + |
| 9 | +ここでは、 **ベーシック** に Nuxt.js の機能を使う方法を焦点を当てて解説しています。 |
| 10 | + |
| 11 | +## SSR時のerror関数の有用性 |
| 12 | + |
| 13 | +SSR の場合で axios の http エラーが発生した場合は、 |
| 14 | + |
| 15 | +ブラウザからアクセスする URL のレスポンスが `error` 関数に渡す `statusCode` になります。 |
| 16 | + |
| 17 | +つまり、 `layout/error.vue` が画面には表示されますが、 URL のレスポンスは 401 や 500 など指定したものになります。 |
| 18 | + |
| 19 | +CSR の場合は、 error 関数でただエラー画面が表示されます。 |
| 20 | + |
| 21 | +## asyncDataでのエラーハンドリング |
| 22 | + |
| 23 | +```javascript |
| 24 | +public async asyncData({ $axios, app, error }: any): Promise<void> { |
| 25 | + // try-catch パターン |
| 26 | + try { |
| 27 | + await $axios.$get(`http://localhost:5000/status/${app.$C.HTTP_STATUS.OK}`) |
| 28 | + } catch (err) { |
| 29 | + error({ |
| 30 | + statusCode: err.response.status, |
| 31 | + message: err.message |
| 32 | + }) |
| 33 | + } |
| 34 | +} |
| 35 | +``` |
| 36 | + |
| 37 | +## fetchでのエラーハンドリング |
| 38 | + |
| 39 | +```javascript |
| 40 | +public async fetch({ app, store, error }: any): Promise<void> { |
| 41 | + // try-catch パターン |
| 42 | + try { |
| 43 | + await store.dispatch('http-status/fetchHttpStatus', app.$C.HTTP_STATUS.OK) |
| 44 | + } catch (err) { |
| 45 | + error({ |
| 46 | + statusCode: err.response.status, |
| 47 | + message: err.message |
| 48 | + }) |
| 49 | + } |
| 50 | +} |
| 51 | +``` |
| 52 | + |
| 53 | +## asyncData、fetch以外でのエラーハンドリング |
| 54 | + |
| 55 | +```javascript |
| 56 | +public async onClick() { |
| 57 | + // await-catch パターン |
| 58 | + const response = await this.$axios |
| 59 | + .get( |
| 60 | + `http://localhost:5000/status/${this.$C.HTTP_STATUS.SERVICE_UNAVAILABLE}` |
| 61 | + ) |
| 62 | + .catch(err => { |
| 63 | + return err.response |
| 64 | + }) |
| 65 | + |
| 66 | + if (response.status !== this.$C.HTTP_STATUS.OK) { |
| 67 | + this.$nuxt.error({ |
| 68 | + statusCode: response.status, |
| 69 | + message: response.data |
| 70 | + }) |
| 71 | + // ここの return が重要で、これがないとこれ以降の処理が継続してしまう |
| 72 | + return |
| 73 | + } |
| 74 | + |
| 75 | + console.log('onClick success') |
| 76 | +} |
| 77 | +``` |
| 78 | + |
| 79 | +`this.$nuxt.error` で TypeScript のエラーが出る場合は、 `src/@types/nuxt.d.ts` を作成して、以下を記載するとエラーが消えます。 |
| 80 | + |
| 81 | +```javascript |
| 82 | +import { ErrorParams } from '@nuxt/vue-app' |
| 83 | + |
| 84 | +declare module 'vue/types/vue' { |
| 85 | + interface NuxtApp { |
| 86 | + error(params: ErrorParams): void |
| 87 | + } |
| 88 | +} |
| 89 | +``` |
| 90 | + |
| 91 | +## axiosの共通処理でのエラーハンドリング |
| 92 | + |
| 93 | +```javascript |
| 94 | +import { AxiosError, AxiosRequestConfig } from 'axios' |
| 95 | + |
| 96 | +export default ({ $axios, app, req, error }): void => { |
| 97 | + /** |
| 98 | + * $axios.onResponseError |
| 99 | + */ |
| 100 | + $axios.onResponseError((response: AxiosError): void => { |
| 101 | + console.log('$axios.onResponseError') |
| 102 | + // 通信エラー |
| 103 | + if (!response.response) { |
| 104 | + return |
| 105 | + } |
| 106 | + |
| 107 | + const { status, data } = response.response |
| 108 | + |
| 109 | + // 401 |
| 110 | + if (status === app.$C.HTTP_STATUS.UNAUTHORIZED) { |
| 111 | + const message = app.i18n.t('error.api.status401') |
| 112 | + error({ statusCode: status, message }) |
| 113 | + } |
| 114 | + }) |
| 115 | +} |
| 116 | +``` |
| 117 | + |
| 118 | +## 参考記事 |
| 119 | + |
| 120 | +[Nuxt.js と axios のエラーハンドリング周りの話 - Slide - mya-ake.com](https://mya-ake.com/slides/nuxt-axios-error-handling) |
| 121 | + |
| 122 | +[Nuxt.js で共通のエラーページに遷移させる](https://blog.naoki85.me/posts/68.html) |
| 123 | + |
| 124 | +[Nuxt 404ページへの遷移方法と、メッセージの設定 | Web and Me](http://log.tkyisgk.com/2019/01/14/136/) |
0 commit comments