Help us understand the problem. What is going on with this article?

Vue.jsでタスクキューっぽいものを実現する

More than 1 year has passed since last update.

はじめに

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機能とかを頑張れば同じやり方でできると思います。

やりたいこと

  1. APIへリクエストを送る
  2. APIへのリクエストが完了していない場合は、タスクキューにためて、前の処理が終わってから実行する
  3. 貯める処理は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の通信とか非同期の処理をするときに参考になればと思います。

kouchanne
サーバーサイドエンジニアをやっています。 AWSよりもGCPのほうが得意です。 Vue.jsの記事が多めです。 GCP,Docker,Java,Scala,Python,Vue.js,TypeScript etc...
webcrew
比較見積もりサイト「ズバット」を始め、人々の生活に寄り添う様々な情報サービス事業を展開しています。
https://hrmos.co/pages/1004681658307198976/jobs
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away