はじめに
APIへのリクエストをするときに、連続でリクエストを送るようなシーンで連続送信を防止するために現在の処理が実行中の場合は処理を待つみたいなシーンがありました…
let isConnecting = false
let isRetry =false
api: function () {
if (!isRetry) {
if (!isConnecting) {
isConnectiong = true
axios.get('api')
.then(function(res) {
// 成功時の処理
isConnecting = false
api()
})
} else {
isRetry = true
}
}
}
こうやって書くとネストが深くなって、イケてないですよね
※ 正確にはこれじゃ失敗したときにつみますが
そこで、タスクキュー的なもので処理を予約するみたいなことをやりたいと思いました。
JavaScriptのタスクキュー
いいライブラリが殆どない…
ということで、自分で頑張りました
やってみた
Vue.jsで書いていたので、ここではvue.jsで書いてます。
通常のjavascriptでやるには変数のwatch
機能とかを頑張れば同じやり方でできると思います。
やりたいこと
- APIへリクエストを送る
- APIへのリクエストが完了していない場合は、タスクキューにためて、前の処理が終わってから実行する
- 貯める処理は2つまでで、最終待機しているタスクは最新の状態にしたい
コード
new Vue({
el: "#app",
data: function() {
return {
exQueue: [] // タスクを貯めておく用の配列
}
},
watch: {
// タスクを貯める配列の値に変化があったら呼ばれる関数
exQueue: function(queue) { /*③*/
// タスクが一つのときしか実行されないので、現在実行中の場合は無視される
if (queue.length === 1) {
queue[0].func(queue[0].params)
}
}
},
methods: {
main: function () { /*①*/
this.addQueue({ func: this.callAPI, params: params })
},
// タスクを追加する関数
addQueue: function (job) { /*②*/
// 3の条件を満たすために貯めれるタスクは2つまで
if (this.exQueue.length < 2) {
this.exQueue.push(job)
} else {
// 2つを超えるときは後ろを最新のものに上書きする
this.exQueue.pop()
this.exQueue.push(job)
}
},
// APIを呼び出す関数
callAPI: function(params) { /*④*/
axios.get('api')
.then(function(res) {
// 完了したタスク(配列の先頭を削除する)
this.exQueue.shift()
})
.catch((error => {
console.error('APIからの取得失敗')
}))
}
}
})
解説
- ① → ② → ③ → ④ の順番に実行されていく
- ④ で
exQueue
が更新されるため、 再び ③ が実行される - タスクがある場合は再度実行
- 残タスクがあるうちは繰り返し
といった形で、タスクキューを割と簡単に実装することができます。
さいごに
簡単にVue.jsでタスクキューを実装してみました。
この辺の処理効率化みたいな部分て、ゴリゴリのサーバーサイドよりなコアな言語とかでよく繰り広げられることを見るのですが、JavaScriptだと以外にないなと思い書いてて楽しかったです。※そもそも言語の思想と違う感じはしていますが
とはいえ、if文のネストをしてしまうと、視認性も悪くなったり、ストックしたいタスクを増やすってなると改修が大変になるってことを考えると配列を見てタスクキューだって分かるようになりだいぶシンプルにかけると思います。APIの通信とか非同期の処理をするときに参考になればと思います。