おまじないの綴り方

spelling of a logical spell

ajax通信のライブラリを使いつつ、直列に複数のPOSTを送る

まとめ

  • async/awaitを使うと関数から返ってきたPromiseがresolveされるまで処理を止めることができる
  • ajax通信で通信終了まで待機するには、ajax通信を行う部分をreturn new Promiseでくるみ、通信が終わったらresolveする
  • ajax通信の呼び出し元はawaitしておく

基本形

※ サンプルではajax通信用にsuperagentを使用

https://visionmedia.github.io/superagent/

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"/>
  <!-- superagentのimport -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/superagent/3.8.3/superagent.min.js"></script>
</head>
<body>
  <button onclick="postAll()">post</button>
  
  <script>
    //asyncを先頭につけることでawaitが使えるようになる
    //awaitは戻り値(Promise)がresolveされるまで処理を止めて待機する
    async function postAll(){

      await post()
      await post()

    }

    function post(){

      return new Promise(function(resolve, reject){

        var request = window.superagent
        url = "post先のURL"
        parameter = {
          //postするパラメータ
        }

        request.post(url)
        .send(parameter)
        .end(function(err, res){
          //通信が終わったらresolveする
          resolve()
         })
      })
    }

  </script>

</body>
</html>

変形: ループに適用

postAll()の中身を下記のようにする

    async function postAll(){
      for(var i = 0; i < 10; i++){
        await post()
      }
    }

おまけ: 簡易的な並列度の調整

5こずつ、10こずつなど全部ではないものの複数のjobをまとめて投げたいときもあるので、 一度にpostする量を変数でコントロールできるようにする

※ 全部一気に投げて良いならPromise.Allなどを使ったほうが楽

    async function postAll(){

      //同時に処理するjobの数をコントロールする変数
      concurrency = 10; 

     //一番最後のjobも実行されることを保証したいので、少し多めにforを回す
     //(もっときれいな書き方がありそう)
      for(var i = 0; i < num_job + concurrency; i+=concurrency){

        //post()が返すpromise型の変数を格納する配列
        //この中にjobを追加していく。
        promises = []
        for(var j = 0; j < concurrency; j++){
          job_id = i + j
          //すこし多めにforを回しているため余計なif文がある
          if(job_id < num_job){
            promises.push(post())
          }
        }

        //promisesに入っているjobが全て完了するまで待機
        for(var j in promises){
          await promises[j]
        }
      }
    }