axios/axios: Promise based HTTP client for the browser and node.js
axios は JavaScript の HTTP クライアントであり、よくある web ページから外部 API を叩くために用います。そしてそういった時、常に認証用トークンが通信に付与されたり、開発者ツールを開かずとも web ページ本体を見るだけで通信エラーが起こったことを示す必要があることが多いです。
素朴に通信処理を記述すると次の様に複数個所にトークンを投げる記述をすることになります。
// ある場所の通信 axios.post('https;//hogefuga/api/v1/foo', {}, { headers: { Authorization: `Bearer ${getApiToken()}` } }).then(response => { // 正常処理 }).catch(error => { // 通信失敗処理 // 通信通知用共通処理 alert('通信に失敗しました'); }) // 別のある場所の通信 axios.post('https;//hogefuga/api/v1/bar', { fooId: getFooId(), }, { headers: { Authorization: `Bearer ${getApiToken()}` } }).then(response => { // 正常処理 }).catch(error => { // 通信失敗処理 // 通信通知用共通処理 alert('通信に失敗しました'); })
一々共通の処理(認証、例外)を記述するのは手間です。後の修正時もまとめて変えるには grep だよりになってしまい少々不安です。 interceptors の仕組みで共通化を行います。
axios/axios: Promise based HTTP client for the browser and node.js#interceptors
これは通信にフックしてリクエストやレスポンスを加工する処理を追加する機能で、次のように定義でき、
export const BaseRepository = createAxiosInstance(); function createAxiosInstance(){ // axios.create でいきなり axios を呼んだ時に使われる通信部(AxiosInstance)がインスタンス化される const axiosInstance = axios.create({ // この第一引数オブジェクトで設定を定義 // axios で通信する時の URL の頭を決める。大体ドメインとAPI用URL接頭辞 baseURL: process.env.MIX_BASE_APP_URL, }); // interceptors.request.use で送信時に引数に入れた関数が動作する // 引数で渡ってくるのは axios の設定(送信先や通信方式も持つ今まさに通信を実行しようとしている設定)で、返り値が通信時に実際に使われる axios の設定になる axiosInstance.interceptors.request.use((request)=>{ // もしヘッダーに API トークンを記述するならば request.headers['Authorization'] = `Bearer ${getApiToken()}` // もし URL に APIトークンを増やすならば request.params = request.params || {}; request.params.apiToken = getApiToken(); // リクエスト内容を見るならば console.dir(request) return request; }) // interceptors.response.use で返信時に引数に入れた関数が動作する axiosInstance.interceptors.response.use( (response)=>response, // 第一引数は通信成功時処理。受けた内容をそのまま通過 (error)=>{ // 第二引数は通信失敗時処理 // 通信エラーの内容全体をインデント付きのJSONにして alert 表示 // これだけだととても見難いので適宜プロジェクトに合わせて必要な情報だけ取る処理にした方がベター alert(JSON.stringify(error, ' ', 4)) } ) // interceptor で共通処理を追加した通信機能を返す。 return axiosInstance; }
次の様に使えます。
// グローバル変数 axios の代わりに先述の設定の色々追加された AxiosInstance を BaseRepository 経由で使用する BaseRepository.get('users').then(response => { const data = response.data; return data; });
最初に定義してしまえば残っているのは純粋な Promise による通信処理のみです。通信内容が増えても、変わっても手軽にコーディングできます。