はじめに
VueコンポーネントからVuexのstore内部にAPI非同期通信するためにごにょごにょやっていました。
そこで、store内部でエラーハンドリングしつつ、vueコンポーネントでその結果を受けてアラートを出したり、finally処理をしたいと思ったときに自分用のメモした内容です。
※雰囲気覚えておくためのモノなのでミスしている部分あるかもしれません。
ES2015とかES2017の知識ないと無理でした。
まさかの過去の自分の投稿に救われました。
内容
Vueコンポーネントで、Vuex内部のstoreを通して、axiosライブラリを用いてAPI通信します。
VueやVuexの共有内容も兼ねてなるべく丁寧にお伝えします。
実際の構成と異なり、単純化しています。
また、vue-cliを使用していないので、構成が異なる部分があります。
Nuxt.jsとかから入った人も困惑すると思いますが、基礎部分は同じです。
VueやVuexのおさらい
VueやVuex何て知ってるから早くしろという人は本題まで飛ばしてください。
ファイル構成や流れ、実際のファイルを見ていただくほうが理解できると思うので、記述します。
【ファイル構成】
- public
- index.html
- src
- components
- App.vue
- store
- api.js
- main.js
【流れ】
ざっくり以下の流れになります。
public(index.html) -> src(main.js) -> components(App.vue) -> store(api.js)
【ファイル内容】
ファイル内部を記述します。
細かな部分は端折っています。
<!DOCTYPE html>
<html lang="ja">
<head>
<script src="../src/main.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
「el」要素で「public(index.html)」の「app」に対してrenderする書き方もできます。
import Vue from 'vue';
import store from './store';
import App from './components/App.vue';
new Vue({
store,
render: h => h(App)
}).$mount('#app');
<template>
<div>
<button @click="getApi"></button>
<ul>
<li v-for="list in getApiData">
{{ list }}
</li>
</ul>
</div>
</template>
<script>
import App from './components'
import { mapGetters } from 'vuex'
export default ({
methods: {
getApi(){
this.$store.dispatch('getApiInfoAction', {
url: 'hogehoge.com',
params: 'test'
})
}
},
computed: {
...mapGetters({
getApiData: "getApiInfo"
})
}
})
</script>
import axios from 'axios'
import Vuex from 'vuex'
Vue.use(Vuex);
const state = {
message: "",
}
const getters = {
getApiInfo(state) {
return state.message
}
}
const mutations = {
getApiInfo(state, payload) {
state.message = payload.message
}
}
const actions = {
async getApiInfoAction(context, payload) {
const payload_data = {
message: "",
}
await axios.get(payload.url, { params: payload.params })
.then(response => {
payload_data.message = response.data
}).catch(error => {
payload_data.message = error
}).finally(() => {
context.commit('getApiInfo', payload_data)
})
})
}
}
const store = new Vuex.Store({
state,
getters,
mutations,
actions
})
export default store
本題
APIで処理が失敗したときにもっとキレイにかけないかな、components(App.vue)側でうまくやりたい、またうまくエラーハンドリングしたいという時に役立ったのが、Promiseでした。
自分の過去記事に助けられました。
結論
methods: {
getApi(){
this.$store.dispatch('getApiInfoAction', {
url: 'hogehoge.com',
params: 'test'
}).then(response => {
alert("ok beforeCreate: ", response)
}, error => {
alert("no beforeCreate: ", error)
}).finally(() => {
alert("yeah")
})
}
}
const actions = {
async getApiInfoAction(context, payload) {
const payload_data = {
message: "",
}
await new Promise((resolve, reject) => {
axios.get(payload.url, { params: payload.params })
.then(response => {
payload_data.message = response.data
resolve(response)
}).catch(error => {
payload_data.message = error
reject(error)
}).finally(() => {
context.commit('getApiInfo', payload_data)
})
})
}
}
こうすることで、
APIに成功すれば「resolve」を返し
失敗すれば、「reject」を返してくれるようになり
vueコンポーネント側で良いようにできるようになった。
まとめ
Promiseもasync/await、めっちゃ便利。