49308


下記コードにてABCの順に関数を実行しており、Cにのみajaxの繰り返し処理が含まれています。  
Cのajax処理終了後に最後の仕切り線 console.log("---"); が実行される想定ですが、  
仕切り線が実行されてからajaxのログが流れます。

[code]

    console.log("---");
    funcA();
    funcB();
    funcC();
    console.log("---");
    
    function funcC(){
        const links = ["http://aaa/1","http://aaa/2",・・・]
        for(let i in links){
            runAjax(links[i]);
        }
    }
    
    function runAjax(url_){
        $.ajax({
            type:'GET',
            url: url_,
            timeout: 1000,
            datatype: 'html'
        }).then(data =>{
            console.log(success);
        }, _ =>{
            console.log(error);
        });
    }
    
[/code]

調べるとdeferredやpromiseなどがありましたが使い方がよく分からず、自分のコード内でどう当てはめれば良いのか分からなかったので、質問させていただきました。

(ajax繰り返し時のログの順番もバラバラなのでできれば正しい実行順に直したいです)

ご回答のほど、よろしくお願い致します。

jQuery 3.3.1


CC BY-SA 4.0
2018-10-15T06:28:52.560
49289
2018-10-15T12:49:57.457
30065
question
javascript jquery
ajax繰り返し後の処理


質問内容が不明瞭なので、以下を質問内容として回答します。

  1. ログの出力結果が想定通りにならない
  2. ajax繰り返し時のログの順番がバラバラになってしまう

## 1\. ログの出力結果が想定通りにならない

A. ログの出力結果が想定通りにならないのは、想定が誤っているからです。

$.ajax()は非同期で処理を行います。  
なので、$.ajax()を呼び出すと、ブラウザはHTTPリクエストを送信しますが、  
そのHTTPレスポンスを待つことなく次の関数を実行します。

今回は、funcC()の直後にconsole.log("---")の記述があるため、  
こちらが先に呼び出されます。

その後、少し遅れて、$.ajax()のHTTPリクエストに対するレスポンスが返ってきます。  
レスポンスが返ってくると、  
$.ajax()の戻り値である（jQueryの）Promiseオブジェクトがresolve/rejectされます。

今回は、resolve/rejectされることにより、then()のいずれかの引数の関数が呼び出され、  
console.log(success)/console.log(error)のいずれかが呼び出されます。

## 2\. ajax繰り返し時のログの順番がバラバラになってしまう

A. HTTPレスポンスは、HTTPリクエストを送信した順に返ってくるとは限らないからです。

一般に、複数のHTTPリクエストを送信した場合、  
そのHTTPレスポンスも同じ順で返ってくるとは限りません。

例えば、以下のようなことが起こりえます。

[code]

    HTTPリクエストA,B,Cをごく短い時間に順に送信
    ↓
    HTTPレスポンスBを受信
    ↓
    HTTPレスポンスCを受信
    ↓
    HTTPレスポンスAを受信
    
[/code]

1.の回答を十分理解できたなら、今回のコードでは、funcC()内で、  
ほぼ同時に複数のHTTPリクエストを送信しているのが分かるかと思います。

もし、ログを順に表示したい（HTTPレスポンスを順番に受け取りたい）なら、  
一つ前のHTTPレスポンスを受け取ってから、次のリクエストを送信する必要があります。

jQueryでは、thenを使うことにより、それを実現できます。

[code]

    function funcC(){
    
      const links = ["http://aaa/1","http://aaa/2",・・・]
      if(links.length < 0){
        return;
      }
    
      var promise = runAjax(links[0]);
    
      for(let i = 1; i < links.length; i++){
        promise.then(data => {
           console.log(data);
           return runAjax(links[i]);
        }, _ => {
           console.log("error");
        });
      }
    
      promise.then(data => {
        console.log(data);
      }, _ => {
        console.log("error");
      });
    
    }
    
    
    function runAjax(url_){
      return $.ajax({
        type:'GET',
        url: url_,
        timeout: 1000,
        datatype: 'html'
      });
    }
    
    
    //指定されたURLで順番に通信する
    funcC();
    
[/code]


CC BY-SA 4.0
2018-10-15T12:49:57.457
49308
2018-10-15T12:49:57.457
30533
49289
answer