Skip to content

Instantly share code, notes, and snippets.

@suneo3476
Created February 9, 2016 11:25
Show Gist options
  • Save suneo3476/c8f764708b46652667c9 to your computer and use it in GitHub Desktop.
Save suneo3476/c8f764708b46652667c9 to your computer and use it in GitHub Desktop.
Q. $.ajax#doneで得られたdataを元にコールバック関数内で外側のループを抜けるにはどうしたらよい?
var hoge_func = function(){
var count = 0;
while(true){
var request = $.ajax({
type:"POST",
url:"getData.php",
data: {count: count}
});
request.done(function(data){
if(data == null){
//I wanna finish while loop!!!
}
})
count += 100;
}
}
@gaogao-9
Copy link

gaogao-9 commented Feb 9, 2016

どうしてもwhile(true)では解決できないんだけれども、再帰的に呼び出す(※厳密な意味での再帰ではない)ことをすれば出来ますね。
やりたい処理はこんな感じかな?

var hoge_func = function(callback){
    var count = 0;
    var values = [];

    // 内部関数を呼び出して再帰処理する
    loop();

    function loop(){
        var request = $.ajax({
            type:"POST",
            url:"getData.php",
            data: {count: count}
        });
        request.done(function(data){
            if(data == null){
                // このタイミングで終了するため、終了関数を呼ぶ
                callback(values);
                return;
            }

            // データを積む
            values.push(data);

            // 関数を再帰呼び出しして次のajaxをはじめる
            count += 100;
            loop();
        });
    }
};


// 初期値を指定してhoge_funcの再帰処理を始める
hoge_func(function(values){
    // valuesにはhoge_funcの中身がなくなるまでの間のdataが順番に入っている

    console.log(values[0]); // count=0の時のdata
    console.log(values[1]); // count=100の時のdata
    console.log(values[2]); // count=200の時のdata
    // ...(以下略)
});

@ochaochaocha3
Copy link

終了フラグを用意してポーリングすれば実現できるでしょうか?

var hoge_func = function () {
  var count = 0;
  var finished = false; // 終了フラグ

  while (!finished) {
    var request = $.ajax({
      type: "POST",
      url: "getData.php",
      data: { count: count }
    });
    request.done(function (data) {
      if (data === null) {
        finished = true; // クロージャなので外の変数が見える
      }
    }); // セミコロンが抜けてました
    count += 100;
  }
}; // この書き方では function は式なのでセミコロンが必要

ただ、それ以前の問題として、せっかく ajax で非同期通信しているのに、while ループでブロックしてその間ブラウザを固まらせてしまうのは変な気がします。うまく状態を組んでやって、最後までノンブロックで通すようにはできないでしょうか?

@ochaochaocha3
Copy link

非同期通信の逐次処理については、jQuery なら Deferred、ES6 なら Promise があるようです。

@gaogao-9
Copy link

これをこっそり記事(の中に使用する例題)にしたので事後報告しておきます。
JavaScriptは如何にしてAsync/Awaitを獲得したのか Qiita版

DeferredでもPromiseでも同様なのですが、Generator/Iteratorもしくはtj/coライブラリもしくはasync/awaitを使わない場合(つまり純粋なDeferredやPromiseだけの使用)の場合は、先の通り、どうあがいても再帰処理を記述する必要があります。

そういうことを淡々と書いてる記事です。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment