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] } } }