Vuexのactionsの中で逐次処理を行いたいことがあり若干書き方に悩んだので備忘録として残しておきます。
仕様
- axiosなどを用いて非同期にAPIを叩く=>結果を使って何かしらの処理をする(ex. 取得したデータのexport)
- ↑の処理を結果として取得しうる件数に応じて複数回ループさせたい(ex. 結果が1000件で1度に100件ずつ取得したい場合 => 10回処理を回す)
- ↑の一連の処理をVuexのactionsのなかで行いたい
実装
const store = new Vuex.Store({
state: {
num: 1,
fetchSize: 100
},
mutations: {
processStepByStep(state, data) {
// 何かしらの処理
},
setNumber(state, data) {
state.num = data;
},
setTotal(state, data) {
state.total = data;
}
},
actions: {
async process({ commit, state }) {
do {
// APIリクエストを発行しリソースを取得する, this.$axiosの第2引数でstateを渡せば何件取得するかを指定できるという想定
const res = await this.$axios.get('sample/url', {query: state});
// 何回ループを回すのか閾値を取得, res.totalでリソースの合計件数を取得できる想定
const threshold = Math.ceil(res.data.total / state.fetchSize);
// res.dataで返り値を取得して何かしらの逐次処理を行う
commit('processStepByStep', res.data);
// state.numを更新
commit('setNumber', state.num++);
} while (state.num <= threshold)
}
}
});
解説
- axiosなどを使ってHTTPリクエストを発行するとその返り値はPromiseなので単純に変数には格納できない
- =>
await式
を使えば変数に格納して同期処理をしているかのように扱うことができる
- =>
- 1回以上複数回ループする可能性がある場合
do-while構文
が便利-
state.fetchSize
で1回のAPIリクエスト実行で取得する件数を指定しているのでこの件数以上取得できるようであればループが複数回実行される
-
- 1件あたりのリソース取得件数, リソースの取得開始位置は外部変数なのでstateで定義し直接actionsのなかで扱わないようにする
終わりに
Promise.all()
とかを使った方がいいのかなと最初考えたのですが余計な一時変数が増えたりしそうだなと思ってawaitを使った処理に落ち着きました、もっといい書き方がありそうなので思いついたら適宜更新します