vue.jsを使ってaxiosを学ぶ
axiosはPromiseベースのHTTPクライアントでVue.jsに限らずフロントエンドのフレークワークで利用することができるだけではなく、バックエンドのNode.jsでも利用することができる便利なライブラリです。バックエンドサーバを含め外部のサービスからデータを取得したい時に利用することができます。本文書ではVue.jsのバージョン2とバージョン3の環境におけるaxiosの利用方法について確認していきます。Vue 3についてはOptions APIでの利用方法だけではなくComposition APIでの利用方法についても説明しています。さらにTypeScriptについても記述しています。
Reactでaxiosを利用した場合の利用方法について本サイトで公開しています。
axiosライブラリの代替としてfetch APIを利用することができます。fetch APIはaxiosライブラリとは異なりライブラリを追加インストールすることなく利用することができます。
目次
vue.js+axiosの使える環境を構築
Vue.jsを使ってaxiosの使用方法を学ぶことが目的の場合にはCDNを使うのが一番はやく簡単です(本番環境でCDNを利用することは推奨されていません)。今回は下記のHTMLを元にaxiosの動作確認を行っていきます。任意の場所にindex.htmlファイルを作成してください。
ファイル作成後はブラウザでアクセスしHello Axiosが表示されることを確認してください。axiosが何かわからない人は後ほど説明を行っているので安心してください。
Make sure to use the production build (*.prod.js) when deploying for production.”メッセージが表示されます。
Vue2の場合
利用しているCDNから利用しているVue.jsのバージョンが確認でき、動作確認時のバージョンは2.7.14です。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>vueを使ってaxiosを学ぶ</title>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello Axios',
},
});
</script>
</body>
</html>
Vue3のOptions APIの場合
利用しているCDNではVue3のバージョンは最新バージョンとなります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>vueを使ってaxiosを学ぶ</title>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
</div>
<script src="https://unpkg.com/vue@3"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
Vue.createApp({
el: '#app',
data() {
return {
message: 'Hello Axios',
};
},
}).mount('#app');
</script>
</body>
</html>
Vue3のComposition APIの場合
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>vueを使ってaxiosを学ぶ</title>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
</div>
<script src="https://unpkg.com/vue@3"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
const { createApp, ref } = Vue;
createApp({
setup() {
const message = ref('Hello Axios');
return {
message,
};
},
}).mount('#app');
</script>
</body>
</html>
JSONPlaceholder
自社(個人)以外が運営している外部のサーバからaxiosを使ってデータを取得することができれば、内部/外部問わずどのようなサービスからでもデータを取得することに対する技術的不安がなくなります。そのため今回は無料の外部サービスであるJSONPlaceholderを使用します。
JSONPlaceholderはFake online REST API for developersと説明されている通り、開発者がREST APIの動作確認を行うためのインターネット上の無償のサイトです。このサイトを利用すればaxiosの動作確認するために事前にデータを準備する必要がありません。
axiosの使用方法
axiosとは
axiosはPromiseベースのHTTP ClientライブラリでGETやPOSTのHTTPリクエストを使ってサーバからデータの取得、サーバへのデータ送信を通してデータの追加、更新、削除を行うことができます。
GETメソッドによるデータ取得
GETメソッドは一番シンプルなメソッドでaxiosのみならず外部から情報を取得する際の基本となるHTTPのリクエストメソッドの一つです。ブラウザからWEBサーバにアクセスする際もGETメソッドを利用してWEBページに表示するために必要な情報を取得しています。
JSONPlaceholderにはGETメソッドで取得することができる6つのリソースが準備されています。一番データ取得数の少ないusersから情報を取得してみましょう。
ブラウザからhttps://jsonplaceholder.typicode.com/usersにアクセスしてもusersのデータを確認することができるのでaxiosを利用する前にどのような情報が取得できるかを確認することができます。本文書では戻されるデータの中でidとnameのみ注目します。
axiosのGETメソッドの基本書式は下記のとおりです。getの引数にURLを入れるだけでURLに対してGETリクエストを送ることができます。リクエスト後に戻される値はすべてresponseの中に保存されます。
axios.get('/user?ID=12345')
.then(function (response) {
// handle success(axiosの処理が成功した場合に処理させたいことを記述)
console.log(response);
})
.catch(function (error) {
// handle error(axiosの処理にエラーが発生した場合に処理させたいことを記述)
console.log(error);
})
.finally(function () {
// always executed(axiosの処理結果によらずいつも実行させたい処理を記述)
});
async, awaitを利用した場合は上記の基本書式と記述方法が変わり、try,catchを利用します。
try {
// handle success(axiosの処理が成功した場合に処理させたいことを記述)
const response = await axios.get(
'/user?ID=12345'
);
console.log(response.data);
} catch (error) {
// handle error(axiosの処理にエラーが発生した場合に処理させたいことを記述)
console.log(error);
} finally {
// always executed(axiosの処理結果によらずいつも実行させたい処理を記述)
console.log('message');
}
Vueインスタンスの中でaxiosのGETメソッドを利用します。mountedの中にaxiosの実行コードを記述しているため、ブラウザでこのファイルを閲覧するとaxiosが実行されます。console.logでresponseを指定しているのでデベロッパーツールを使って実行結果を確認することができます。
【Vue 2の場合】
new Vue({
el: '#app',
data: {
message: 'Hello Axios'
},
mounted :function(){
axios.get('https://jsonplaceholder.typicode.com/users')
.then(response => console.log(response))
.catch(error => console.log(error))
}
})
async, await関数を利用した場合は下記のように書き換えることができます。
new Vue({
el: '#app',
data: {
message: 'Hello Axios',
},
async mounted() {
try {
const response = await axios.get(
'https://jsonplaceholder.typicode.com/users'
);
console.log(response.data);
} catch (error) {
console.log(error);
}
},
});
【Vue 3のoptions APIの場合】
Vue.createApp({
el: '#app',
data(){
return {
message: 'Hello Axios',
}
},
mounted(){
axios.get('https://jsonplaceholder.typicode.com/users')
.then(response => console.log(response))
.catch(error => console.log(error))
}
}).mount('#app')
【Vue 3のcomposition APIの場合】
Composition APIを利用した場合にはrefやonMountedを利用尾する場合には忘れずにimportする必要があります。
const { createApp, ref, onMounted } = Vue;
createApp({
setup() {
const message = ref('Hello Axios');
onMounted(() => {
axios
.get('https://jsonplaceholder.typicode.com/users')
.then((response) => console.log(response))
.catch((error) => console.log(error));
});
return {
message,
};
},
}).mount('#app');
Composition APIでasync, await関数を利用した場合は下記のように記述することができます。
const { createApp, ref, onMounted } = Vue;
createApp({
setup() {
const message = ref('Hello Axios');
onMounted(async () => {
try {
const response = await axios.get(
'https://jsonplaceholder.typicode.com/users'
);
console.log(response.data);
} catch (error) {
console.log(error);
}
});
return {
message,
};
},
}).mount('#app');
コンソールには、responseオブジェクトのdataプロパティに10件分のユーザデータが入っていることが確認できます。これでaxiosのGETメソッドの動作確認は完了です。簡単ですね。
GETメソッドはデータを取得してくるだけの処理なのでその後はVue.jsを使用して取得した内容をブラウザ上に表示させます。
確認した通りresponseオブジェクトのdataプロパティの中にusersのデータが配列として入っているのでVueインスタンスのdataプロパティに取得したデータ(response.data)を保存するusersを追加します。response.dataをusersに入れるように変更を行います。dataプロパティのmessageを削除しています。
【Vue 2の場合】
new Vue({
el: '#app',
data: {
users: []
},
mounted :function(){
axios.get('https://jsonplaceholder.typicode.com/users')
.then(response => this.users = response.data)
.catch(error => console.log(error))
}
})
【Vue 3のoptions APIの場合】
Vue.createApp({
el: '#app',
data(){
return {
users: [],
}
},
mounted(){
axios.get('https://jsonplaceholder.typicode.com/users')
.then(response => this.users = response.data)
.catch(error => console.log(error))
}
}).mount('#app')
【Vue 3のcomposition APIの場合】
const { createApp, ref, onMounted } = Vue;
createApp({
setup() {
const users = ref([]);
onMounted(() => {
axios
.get('https://jsonplaceholder.typicode.com/users')
.then((response) => (users.value = response.data))
.catch((error) => console.log(error));
});
return {
users,
};
},
}).mount('#app');
usersに取得したデータを保存するだけではブラウザに表示されることはできないのでvue.jsのv-forディレクティブを使います。v-forにより配列として保存されているuserオブジェクトを個別に取り出すことができます。取り出したuserオブジェクトのuser.nameのみ表示させています。表示させるものは、user.id, user.username, user.emailでも構いません。
<ul>
<li v-for="user in users" :key="user.name">{{ user.name }}</li>
</ul>
GETメソッドへのクエリパラメータの設定
ユーザ一覧から名前を使って検索を行いたい場合は、ある名前のユーザの情報のみ取得できる処理が必要になります。JSONPlaceholderではその場合はURLにクエリパラメータをつけることで取得することができます。
下記のように指定を行えば、Glenna Reichertという名前の人だけ情報を取得することができます。
axios.get('https://jsonplaceholder.typicode.com/users?name=Glenna Reichert')
.then(response => this.users = response.data)
.catch(error => console.log(error))
axionsではparamsオプションを使用することでもクエリパラメータを追加することができます。
axios.get('https://jsonplaceholder.typicode.com/users',
{
params: {
name: 'Glenna Reichert'
}
})
.then(response => this.users = response.data)
.catch(error => console.log(error))
POSTメソッドによる新規作成
axiosのPOSTメソッドを使うと新規にデータを登録することが可能です。POSTメソッドが行えるかどうかはサーバの設定によるのでPOSTリクエストを送信する場合は事前に確認が必要です。POSTの場合はGETとは違いデータを作成するのに必要なプロパティと値の組をオブジェクトで設定する必要があります。
POSTメソッドの書式は下記のようになります。firstName, lastNameのプロパティを持つオブジェクトを追加しようとする場合は下記のように設定するプロパティと値の組を設定します。2つ以上のプロパティがある場合は同様の方法で必要な情報すべての組を追加します。
axios.post('/users', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
WEBアプリケーションの場合は新規データを追加する場合はユーザに入力してもらうことが大半だと思うのでinput要素を追加しユーザが入力した情報を利用してPOSTリクエストを送信します。Vue.jsを利用するので、input要素にv-modelで新しいdataのnameを設定し、作成ボタンにv-onディレクティブでclickイベントを設定します。ボタンを押すとcreateNewUserメソッドが実行されます。
<div id="app">
<input v-model="name"><br>
<button v-on:click="createNewUser">作成</button>
<ul>
<li v-for="user in users" :kye="user.name">{{ user.name }}</li>
</ul>
</div>
Vue側では新たにdataプロパティnameを追加し、methodsにcreateNewUserメソッドを追加します。
new Vue({
el: '#app',
data: {
users: [],
name: ''
},
methods : {
createNewUser: function(){
axios.post('https://jsonplaceholder.typicode.com/users',{
name: this.name
})
.then(response => this.users.unshift(response.data))
.catch(error => console.log(error))
}
},
mounted :function(){
axios.get('https://jsonplaceholder.typicode.com/users')
.then(response => this.users = response.data)
.catch(error => console.log(error))
}
})
JSONPlaceholderはPOSTメソッドを使って動作確認は行うことができますが、ユーザを追加したからといってサーバ上のデータが追加されるわけではありません。その代わり、追加したデータはresponse.dataの中に入って戻ってきます。JSONPlaceholderの場合は追加したユーザを戻すという仕様です。通常のサービスの場合ではどのような情報が戻ってくるのか確認して処理を行う必要があります。
その戻ってきたデータをunshiftメソッドを使って現在のusersの先頭に追加しています。usersの一番後に登録した場合にはpushメソッドを利用することができます。
then(response => this.users.unshift(response.data))
inputに名前を入力して、作成ボタンを押すと入力フォームで入力したJohn Doeがリストの一番上に表示されます。
Vue3のComposition APIを利用することで下記のように記述することはできます。
const { createApp, ref, onMounted } = Vue;
createApp({
setup() {
const users = ref([]);
const name = ref('');
const createNewUser = () => {
axios
.post('https://jsonplaceholder.typicode.com/users', {
name: name.value,
})
.then((response) => users.value.unshift(response.data))
.catch((error) => console.log(error));
};
onMounted(() => {
axios
.get('https://jsonplaceholder.typicode.com/users')
.then((response) => (users.value = response.data))
.catch((error) => console.log(error));
});
return {
users,
name,
createNewUser,
};
},
}).mount('#app');
DELETEメソッドによるデータの削除
axiosのDELETEメソッドを利用して、データの削除方法を確認します。GETメソッドとは異なりどのデータを削除するかをサーバに伝える必要があるためDELETEするデータを識別するIDが必要となり書式は下記のとおりです。IDは数値だけではなく文字列の場合もあります。
axios.delete('/user/123')
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.finally(function () {
// always executed
});
各リストの行に削除ボタンをつけて、ボタンを押すとdeleteUserメソッドが実行できるように変更を行います。引数には削除するユーザを識別するためのuserのidを設定します。
<li v-for="user in users" :key="user.id">
{{ user.name }}:<button v-on:click="deleteUser(user.id)">削除</button>
</li>
methodsにdeleteUserメソッドを追加します。
クリックを押してもブラウザ上のデータは変化はありません。また、サーバ上のデータも実際にはデータの削除は行われません。DELETEメソッドが成功したことのみデベロッパーツールのログで確認することができます。DELETEメソッドの場合はresponse.dataには何も入っていません。
deleteUser: function (id) {
axios
.delete('https://jsonplaceholder.typicode.com/users/' + id)
.then((response) => console.log(response))
.catch((error) => console.log(error));
},
Vue3のComposition APIを利用することで下記のように記述することはできます。
const { createApp, ref, onMounted } = Vue;
createApp({
setup() {
const users = ref([]);
const name = ref('');
const createNewUser = () => {
axios
.post('https://jsonplaceholder.typicode.com/users', {
name: name.value,
})
.then((response) => users.value.unshift(response.data))
.catch((error) => console.log(error));
};
const deleteUser = (id) => {
axios
.delete('https://jsonplaceholder.typicode.com/users/' + id)
.then((response) => console.log(response))
.catch((error) => console.log(error));
};
onMounted(() => {
axios
.get('https://jsonplaceholder.typicode.com/users')
.then((response) => (users.value = response.data))
.catch((error) => console.log(error));
});
return {
users,
name,
createNewUser,
deleteUser,
};
},
}).mount('#app');
削除ボタンをクリック後にクリックしたユーザを画面上のユーザ一覧から削除したい場合には以下のようにfilter関数を利用して行うこともできます。クリックしたユーザのidと一致しないユーザのみfilterによって取得しているのでクリックしたユーザが削除されることになります。
const deleteUser = (id) => {
axios
.delete('https://jsonplaceholder.typicode.com/users/' + id)
.then(
() =>
(users.value = users.value.filter((user) => user.id !== id))
)
.catch((error) => console.log(error));
};
PATCHメソッドによるユーザの更新
axiosのPATCHメソッドを利用して、データの更新方法を確認します。PATCHでは既存のデータの上書きを行うので、更新したい項目と値の組を指定する必要があります。また更新するユーザを識別するIDも必須となります。
axios.patch('/user/123',{
firstName: 'Jone',
lastName : 'Dow'
})
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.finally(function () {
// always executed
});
更新の場合はユーザ情報を変更するフォームが必要となりvue.js側の設定が少し複雑になるため本書では変更フォームの作成は行いません。その変わりaxiosの更新処理を確認するためvue.jsのマウント時のライフサイクルフックのmountedでidが1のユーザの名前の更新を行います。PATCHの場合はJSONPlaceholderでは更新したユーザの”全情報”が戻ってくるので、その情報をブラウザに表示させるためにunshiftを利用しています。
mounted :function(){
axios.patch('https://jsonplaceholder.typicode.com/users/1',{
name: 'John Doe'
})
.then(response => this.users.unshift(response.data))
.catch(error => console.log(error))
}
Vue3のComposition APIを利用してunshiftではなくidの値に1を持つユーザの名前を変更します。変更するユーザはfindメソッドを利用してJSONPLACEHolderから戻されるユーザの名前を使って更新を行います。
const { createApp, ref, onMounted } = Vue;
createApp({
setup() {
const users = ref([]);
const name = ref('');
const createNewUser = () => {
axios
.post('https://jsonplaceholder.typicode.com/users', {
name: name.value,
})
.then((response) => users.value.unshift(response.data))
.catch((error) => console.log(error));
};
const deleteUser = (id) => {
axios
.delete('https://jsonplaceholder.typicode.com/users/' + id)
.then(
() =>
(users.value = users.value.filter((user) => user.id !== id))
)
.catch((error) => console.log(error));
};
onMounted(() => {
axios
.get('https://jsonplaceholder.typicode.com/users')
.then((response) => (users.value = response.data))
.catch((error) => console.log(error));
axios
.patch('https://jsonplaceholder.typicode.com/users/1', {
name: 'John Doe',
})
.then((response) => {
const user = users.value.find((user) => user.id === 1);
user.name = response.data.name;
})
.catch((error) => console.log(error));
});
return {
users,
name,
createNewUser,
deleteUser,
};
},
}).mount('#app');
ページを開いた瞬間は先頭のユーザの名前は”Leanne Graham”になっていますがすぐに”John Doe”に上書きされます。
ここまでの説明でaxiosを利用したGET, DELETE, POST, PATCHメソッドの方法を理解することができました。
Responseの中身の確認
これまでresponse.dataの中身にだけ注目してきましたが、responseに含まれる他のデータも確認しておく必要があります。
dataだけではなく、status, headers, statusText, configがあります。statusだけに注目すればGETメソッドで処理が成功した場合はstatusコード200に戻され、POSTメソッドの場合はstatusコード201が戻されることが確認できます。
axios.get('https://jsonplaceholder.typicode.com/users')
.then(response => {
console.log(response.data)
console.log(response.status)
console.log(response.headers)
console.log(response.statusText)
console.log(response.config)
})
.catch(error => console.log(error))
}
エラーについて
ここまでのaxiosの処理ではエラーが発生しませんでしたが通常はエラーが発生する可能があります。axiosの実行時にエラーが発生した場合のcatchの処理について意図的にエラーを発生させて動作を確認しておきましょう。
URLを間違えた場合はリクエスト処理は正常に行うことができません。その場合はcatchに記述した内容が実行されます。そのような場合はブラウザだけを見てもデータが表示されないだけで何が行っているのかわかりません。エラーが発生していることをブラウザに表示できるようにコードを更新します。
VueのdataプロパティにerrorFlagを追加します。
data: {
users: [],
name: '',
errorFlag: false
},
errorFlagがtrueの時だけメッセージが表示されるようにv-showディレクティブを使用します。v-ifでも構いません。
<div id="app">
<p v-show="errorFlag">サーバとの通信にエラーが発生しています</p>
エラーが発生してcatchの処理に行った場合のみerrorFlagをtrueに変更します。
axios.get('https://jsonplaceholder.typicode.com/user')
.then(response => this.users = response.data)
.catch(error =>{
console.log(error.response)
this.errorFlag = true;
}
)
間違ったURLに変更すると404エラーが発生するので画面上部にエラーメッセージが発生します。
ここでは簡単に説明をしましたが、axiosは非常に使いやすいので処理が失敗することはないのではという錯覚で使ってしまいがちですがエラーが発生した際にどのような処理を行うかをしっかり考える必要があります。
errorについてはerror.response以外にもerror.name, error.message, error.request, JSON.stringify(error)などいろいろな取得方法があるので一度確認をしてくみてください。
.catch((error) => {
console.log(error);
console.log(JSON.stringify(error));
console.log(error.name);
console.log(error.message);
console.log(error.request);
console.log(error.response);
});
リクエストの設定
ここまではget, postなどリクエストに関する動作確認の説明を行ってきましたがそれ以外にリクエストに関する設定を行うことができます。利用頻度が高く各所で利用されている設定を中心に説明を行なっています。
baseURLの設定
本文書は短いコードなのでコード中にアクセス先であるhttps://jsonplaceholder.typicode.com/を何度も記述することはありませんでしたがアプリケーションを構築する場合に何度も同じURLを記述するのは冗長になります。axiosではdefaultsでアクセスするドメインのURLを設定することができます。
axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com';
baseURLを設定した場合はgetメソッドを実行する場合にbaseURLで設定したURLは省略することができます。
mounted() {
axios
.get('/users') //baseURLを設定
.then((response) => (this.users = response.data))
.catch((error) => {
console.log(error);
});
},
下記のようにbaseURLを利用してコードを書き換えることができます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>vueを使ってaxiosを学ぶ</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="user in users" :key="user.id">{{ user.name }}</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com';
new Vue({
el: '#app',
data: {
users: [],
},
mounted: function () {
axios
.get('/users')
.then((response) => (this.users = response.data))
.catch((error) => console.log(error));
},
});
</script>
</body>
</html>
baseURLの設定が行われているか確認したい場合にはaxiosのインスタンスを作成することが確認することができます。
const instance = axios.create();
console.log(instance.defaults.baseURL);
ブラウザのデベロッパーツールのコンソールにはbaseURLが表示されます。
https://jsonplaceholder.typicode.com
Headerの設定
認証に利用するTokenなどをHeaderに設定したい場合があります。defaults値に設定することでaxiosでリクエスト毎にヘッダーに設定をする必要がなくなります。token_idにはサーバから取得したトークン情報を保存します。
axios.defaults.headers.common['Authorization'] = `Bearer ${token_id}`;
インスタンスの作成
createメソッドを利用してaxiosのインスタンスを作成することができます。createメソッドの引数でbaseURLの設定を行うこともできます。
const baseURL = 'https://jsonplaceholder.typicode.com';
const headers = {
Authorization: `Bearer ${token_id}`
}
const axiosInstance = axios.create({
baseURL,
headers
});
axiosInstance.get('user');
Interceptorsの設定
axiosからリクエストを送信する前、またサーバからレスポンスが戻ってきた際にRequest, Responseオブジェクトに対して処理を追加することができます。
Requestでの設定
例えばリクエストの設定内容を確認したい場合は下記のように記述することで確認することができます。
axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com';
axios.interceptors.request.use((config) => {
console.log(config)
return config;
});
interceptorsを利用してaxiosの設定情報を確認しています。configの中にはbaseURLの内容も確認することができます。
設定は見るだけではなく設定することも可能です。baseURLの設定をinterceptorsの中で行ってみます。
axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com';
axios.interceptors.request.use((config) => {
config.baseURL = 'https://test.com';
console.log(config)
return config;
});
baseURLが上書きされていることが確認できます。https://test.comにはアクセスできないのでエラーにはなります。
axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com';
axios.interceptors.request.use((config) => {
config.baseURL = 'https://test.com';
console.log(config)
return config;
});
responseでの設定
responseではステータスコードなどサーバ側から戻ってきた情報を確認することができます。
axios.interceptors.response.use((response) => {
console.log(response);
return response;
});
responseは認証が行われている環境で認証に失敗しステータスコード401(Unauthorized)が戻ってきた場合にlogout処理を行うといった使い方があります。各レスポンスのステータスコードを確認することでそれぞれのコードに応じた処理を実装することができます。
axios.interceptors.response.use(
(response) => response,
(error) => {
if (error.response.status === 401) {
//logoutの処理を記述する
}
return Promise.reject(error);
}
);
ファイルアップロードの進捗確認
axiosを利用してサーバへファイルのアップロードを行いたい場合ファイルのアップロードの進捗状況を知りたい場合にプログレスバーが利用されます。
axiosでも現在のアップロードの進捗方法を知ることができます。第3引数に下記のように設定を行い、progressEventでファイル全体のサイズprogressEvent.totalとアップロードされたサイズprogressEvent.loadedで確認することができます。
const form = new FormData();
form.append('file',event.dataTransfer.files[0]);
axios.post('/api/karte_file',form,{
onUploadProgress: progressEvent => {
console.log(progressEvent.loaded)
console.log(progressEvent.total)
}
});
この値を割ると全体に対する現在の進捗具合をしることができます。
ratio = Math.floor((progressEvent.loaded)*100/progressEvent.total) + '%';
Vue.jsのPluginで利用
axiosをVue.jsのPluginを利用して設定した場合についても設定方法を確認しておきます。動作確認はVue3のComposition APIでscript setupを利用しています。Options APIとは設定方法が異なりprovide, inject関数を利用します。
Vue3 Composition APIの場合
Pluginの設定を行うためここまではCDNを利用していましたがここではプロジェクトの作成を行います。npm init vueコマンドを実行すると利用する機能の選択を行うことができますがPluginの設定を行うためだけなのでここでは何も選択せずNoを選択します。
% npm init vue@latest
Need to install the following packages:
create-vue@latest
Ok to proceed? (y) y
Vue.js - The Progressive JavaScript Framework
✔ Project name: … vue-axios-plugin
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit Testing? … No / Yes
✔ Add Cypress for both Unit and End-to-End testing? … No / Yes
✔ Add ESLint for code quality? … No / Yes
Scaffolding project in /Users/mac/Desktop/vue/vue-axios-plugin...
プロジェクトの作成が完了したら作成されたプロジェクトフォルダに移動してnpm installを実行します。axiosのインストールも行います。
% cd vue-axios-plugin
% npm install
% npm install axios
プロジェクトフォルダのsrcフォルダの下にpluginsフォルダを作成してaxios.jsファイルを作成します。axiosのPluginファイルを作成します。オプションではbaseURLを設定できるようにしています。
import axios from 'axios';
const axiosPlugin = {
install(app, options) {
axios.defaults.baseURL = options.baseURL;
app.provide('axios', axios);
},
};
export default axiosPlugin;
axiosのcreateメソッドを利用して設定することもできます。
import axios from 'axios';
const axiosPlugin = {
install(app, options) {
const axiosInstance = axios.create({
baseURL: options.baseURL,
});
app.provide('axios', axiosInstance);
},
};
export default axiosPlugin;
Pluginをvueから利用できるようにするためmain.jsファイルを更新します。provide関数を利用して他のコンポーネントでもaxiosが利用できるように設定しています。
import './assets/main.css';
import { createApp } from 'vue';
import App from './App.vue';
import axios from './plugins/axios';
const app = createApp(App);
app.use(axios, {
baseURL: 'https://jsonplaceholder.typicode.com/',
});
app.mount('#app');
Appコンポーネントから設定したaxiosのプラグインを利用します。利用する場合はinjectを関数を利用します。
<script setup>
import { onMounted, inject } from 'vue';
const axios = inject('axios');
onMounted(async () => {
const response = await axios.get('/users');
console.log(response.data);
});
</script>
<template></template>
npm run devコマンドで開発サーバを起動してブラウザのコンソールを見ると取得したユーザ一覧が配列で確認できます。VueのPluginを利用してaxiosを利用することができました。
TypeScriptの場合
プロジェクトの作成
TypeScriptを利用した場合の動作確認も行っておきます。TypeScript環境もnpm init vue@latestコマンドを実行してプロジェクトの作成を行います。プロジェクトを作成する場合には”Add TypeScript”で”Yes”を選択してください。
% npm init vue@latest
Vue.js - The Progressive JavaScript Framework
✔ Project name: … vue3-axios
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit Testing? … No / Yes
✔ Add an End-to-End Testing Solution? › No
✔ Add ESLint for code quality? … No / Yes
Scaffolding project in /Users/mac/Desktop/vue3-axios...
Done. Now run:
cd vue3-axios
npm install
npm run dev
プロジェクトフォルダに移動して、npm installコマンドを実行します。axiosのインストールも行います。
% cd vue3-axios
% npm install
% npm install axios
axiosをインストールすると型情報も一緒にインストールされます。型情報はnode_modules/axios/index.d.tsファイルから確認できます。
TypeScriptの設定
TypeScriptを利用する場合はsetup scriptにlang=”ts”を追加します。
GETリクエスト
App.vueファイルに以下のコードを記述してユーザ一覧を表示しています。axiosのgetリクエストの戻り値はUserオブジェクトが入った配列なのでAxiosResponseには戻される型であるUser[]を指定します。これでresponse.dataにはUser[]の型を持つデータが入っていることがわかります。
<script setup lang="ts">
import { ref } from 'vue';
import axios from 'axios';
import type { AxiosResponse, AxiosError } from 'axios';
type User = {
id: string;
name: string;
};
const users = ref<User[]>([]);
axios
.get('https://jsonplaceholder.typicode.com/users')
.then((response: AxiosResponse<User[]>) => {
users.value = response.data;
})
.catch((error: AxiosError) => {
console.log(error.message);
});
</script>
<template>
<ul>
<li v-for="user in users" :key="user.id">
{{ user.name }}
</li>
</ul>
</template>
node_modules/axios/index.d.tsファイルを見るとUser[]がdataの型に対応していることがわかります。
export interface AxiosResponse<T = any, D = any> {
data: T;
status: number;
statusText: string;
headers: RawAxiosResponseHeaders | AxiosResponseHeaders;
config: InternalAxiosRequestConfig;
request?: any;
}
npm run devコマンドを実行して開発サーバを起動してユーザ一覧が表示されれば正常に動作しています。
try, catchを利用した場合
try, catchを利用した場合のTypeScriptを利用した場合のコードを確認しておきます。
<script setup lang="ts">
import { ref } from 'vue';
import axios from 'axios';
import type { AxiosResponse } from 'axios';
type User = {
id: string;
name: string;
};
const users = ref<User[]>([]);
const getUsers = async () => {
try {
const response: AxiosResponse<User[]> = await axios.get(
'https://jsonplaceholder.typicode.com/users'
);
const data = await response.data;
users.value = data;
} catch (error) {
if (axios.isAxiosError(error)) {
console.log(error.message);
} else {
console.log(error);
}
}
};
getUsers();
</script>
<template>
<ul>
<li v-for="user in users" :key="user.id">
{{ user.name }}
</li>
</ul>
</template>
catchのerrorにAxiosErrorの型を設定すると”Catch clause variable type annotation must be ‘any’ or ‘unknown’ if specified.ts(1196)”のエラーが発生するのでaxiosが持つisAxiosErrorメソッドを利用したType Guardによりエラーなしでerror.messageにアクセスすることができます。
isAxiosErrorについてはaxiosのGitHubのページに記載されています。
POSTリクエスト
POSTリクエストの場合のTypeScriptを利用した場合のコードも確認しておきます。
<script setup lang="ts">
import { ref } from 'vue';
import axios from 'axios';
import type { AxiosResponse, AxiosError } from 'axios';
type User = {
id: string;
name: string;
};
const users = ref<User[]>([]);
const name = ref<string>('');
axios
.get('https://jsonplaceholder.typicode.com/users')
.then((response: AxiosResponse<User[]>) => {
users.value = response.data;
})
.catch((error: AxiosError) => {
console.log(error.message);
});
const createNewUser = () => {
axios
.post('https://jsonplaceholder.typicode.com/users', {
name: name.value,
})
.then((response: AxiosResponse<User>) => users.value.unshift(response.data))
.catch((error: AxiosError) => console.log(error.message));
};
</script>
<template>
<input v-model="name" /><br />
<button v-on:click="createNewUser">作成</button>
<ul>
<li v-for="user in users" :key="user.id">
{{ user.name }}
</li>
</ul>
</template>
try, catchを利用した場合
try, catchを利用した場合のTypeScriptを利用した場合のコードを確認しておきます。
<script setup lang="ts">
import { ref } from 'vue';
import axios from 'axios';
import type { AxiosResponse } from 'axios';
type User = {
id: string;
name: string;
};
const users = ref<User[]>([]);
const name = ref<string>('');
const getUsers = async () => {
try {
const response: AxiosResponse<User[]> = await axios.get(
'https://jsonplaceholder.typicode.com/users'
);
const data = await response.data;
users.value = data;
} catch (error) {
if (axios.isAxiosError(error)) {
console.log(error.response?.status);
} else {
console.log(error);
}
}
};
getUsers();
const createNewUser = async () => {
try {
const response: AxiosResponse<User> = await axios.post(
'https://jsonplaceholder.typicode.com/users',
{
name: name.value,
}
);
users.value.unshift(response.data);
} catch (error) {
if (axios.isAxiosError(error)) {
console.log(error.response?.status);
} else {
console.log(error);
}
}
};
</script>
<template>
<input v-model="name" /><br />
<button v-on:click="createNewUser">作成</button>
<ul>
<li v-for="user in users" :key="user.id">
{{ user.name }}
</li>
</ul>
</template>
axios.getやaxios.postにも処理後に戻されるデータの型をジェネリクスで型を設定することができます。
const response: AxiosResponse<User[]> = await axios.get>User[]>(
'https://jsonplaceholder.typicode.com/users'
);