これはなに
Nuxt.jsでのaspidaを使ったAPI通信について、
API呼び出し箇所でエラーハンドリングするのではなく、共通的にエラーハンドリングする方法を記載します。
また、一部のAPI呼び出しにおいて、例外的に共通のエラーハンドリングを実行しないようにする方法も記載しています。
生のaxiosを使っている場合どうやるかは記載してません。
先に結論
- pluginsにてaxios.onError()を設定することで共通のエラーハンドリングをかける
- API呼び出し時のconfigに独自の値を入れることで、共通のエラーハンドリングで処理を分岐できる
- configに独自の値を入れるために型を拡張する必要がある
やり方
nuxt.config.js
axiosモジュールの追加と、後述するpluginの読み込みを追加します。
const nuxtConfig: Configuration = {
// 略
plugins: [
'@/plugins/axios.ts',
],
// 略
modules: [
'@nuxtjs/axios',
],
// 略
}
plugins
plugins/axios.js
を作成して、axiosの設定を追加しましょう。
import { Context } from '@nuxt/types'
import { AxiosError, AxiosRequestConfig } from 'axios'
import Rollbar from 'rollbar'
// AxiosRequestConfigを拡張して、Nuxtのエラーページを表示するかどうかのフラグを保持できるようにする
export type CustomRequestConfig = AxiosRequestConfig & {
dontDisplayErrorPage?: boolean
}
export default ({ $axio, error }: Context) => {
// ここでaxiosの共通設定を行う
$axios.defaults.timeout = 10000
// NOTE: ここでCustomRequestConfigのプロパティもデフォルト値を設定できれば良いが、型の制約上難しそうだった
// axiosのエラーハンドリングを追加する
$axios.onError((axiosError: AxiosError) => {
const res = axiosError.response
const status = res?.status ?? 500
if ((axiosError.config as CustomRequestConfig)?.dontDisplayErrorPage) {
// api利用時にconfigとして`dontDisplayErrorPage: true`を渡した時のみエラーページの表示をスキップする
return
}
// 共通で実行したいエラー処理
error({ statusCode: status }) // エラーページを表示
})
}
共通エラー処理追加
$axios.onError()
でエラー時の共通処理を書くことができます。
ただし、このままだと全てのAPI呼び出しにおいて、エラー時に同じ処理をしてしまうので、あるAPIだけ違った処理にしたい場合などに対応できません。
そこで、axios呼び出し時のconfigに独自の設定値を渡し、onErrorのタイミングで取得することで処理の分岐を実現します。
axiosの設定値(AxiosRequestConfig)型の拡張
export type CustomRequestConfig = AxiosRequestConfig & {
dontDisplayErrorPage?: boolean
}
このようにしてプロパティを追加することができます。
api呼び出すところ
共通エラーハンドリングを利用する
共通エラーハンドリングをしたい場合は、普通にaspidaを使ってAPIを呼び出すだけです。
エラーが発生したら、共通のエラーハンドリングが実行されます。
例外的にAPI別にエラーハンドリングをする
例外的に共通エラーハンドリングをスキップしたい場合は以下のようにします。
// 呼び出し処理の例
import api from '@@/apis/$api'
import { AxiosInstance } from 'axios'
import aspida from '@/libs/aspida-shim'
export const callAPI = (axios: AxiosInstance) => {
// <T>にカスタマイズした設定型を入れる
const client = api<CustomRequestConfig>(aspida(axios))
client.api.hogehoge.$get({
config: {
dontDisplayErrorPage: true // 独自のエラーハンドリングをするのでエラーページの表示をしない
timeout: 60000, //通常のオプションも上書きできる
}
})
.then(() => {
console.log('success!')
})
.catch((error: AxiosError) => {
console.dir(error)
// ここに自前でエラーハンドリングを書く
// `dontDisplayErrorPage` オプションをつけているのでエラーページの表示処理はスキップされる
})
}
説明
typescriptを使用している場合は、独自のconfig値を渡そうとしても
configの型がAxiosRequestConfig
型でないためエラーになってしまいます。
これを解決するには、以下のようにします。
// <T>にカスタマイズした設定型を入れる
const client = api<CustomRequestConfig>(aspida(axios))
ここのapi
= '@@/apis/$api'
はaspidaがビルドしたAPIの型情報が記載されたファイルです。
apiは以下のような型定義になっていて、Tに渡した型が、configの型となることがわかります。
const api = <T>({ baseURL, fetch }: AspidaClient<T>) => {
// 略
return {
api: {
hogehoge: {
get: (option?: { config?: T }) =>
fetch<Methods0['get']['resBody']>(prefix, PATH0, GET, option).json(),
// 略
<T>
カスタマイズした設定オブジェクトの型(CustomRequestConfig)を入れてやれば
独自に定義した設定値を使うことができます。
まとめ
- pluginsにてaxios.onError()を設定することで共通のエラーハンドリングをかける
- API呼び出し時のconfigに値を入れることで、共通エラーハンドリングで処理を分岐できる
- configに独自の値を入れるために型を拡張する必要がある
以上、参考になりましたら幸いです。