javascript - 非同期 - when done 効かない




すべてのjQuery Ajaxリクエストが完了するまで待ちますか? (14)

@BBonifieldの答えに基づいて、私はセマフォロジックがすべてのajax呼び出しに広がらないようにユーティリティ関数を書きました。

untilAjaxはすべてのajaxCallが完了したときにコールバック関数を呼び出すユーティリティ関数です。

ajaxObjsはajax設定オブジェクトの配列です[http://api.jquery.com/jQuery.ajax/]

fnはコールバック関数です

function untilAjax(ajaxObjs, fn) {
  if (!ajaxObjs || !fn) {
    return;
  }
  var ajaxCount = ajaxObjs.length,
    succ = null;

  for (var i = 0; i < ajaxObjs.length; i++) { //append logic to invoke callback function once all the ajax calls are completed, in success handler.
    succ = ajaxObjs[i]['success'];
    ajaxObjs[i]['success'] = function(data) { //modified success handler
      if (succ) {
        succ(data);
      }
      ajaxCount--;
      if (ajaxCount == 0) {
        fn(); //modify statement suitably if you want 'this' keyword to refer to another object
      }
    };
    $.ajax(ajaxObjs[i]); //make ajax call
    succ = null;
  };

例: untilAjax関数はuntilAjax使用しuntilAjax

function doSomething() {
  // variable declarations
  untilAjax([{
    url: 'url2',
    dataType: 'json',
    success: function(data) {
      //do something with success data
    }
  }, {
    url: 'url1',
    dataType: 'json',
    success: function(data) {
      //do something with success data
    }
  }, {
    url: 'url2',
    dataType: 'json',
    success: function(response) {
      //do something with success data
    }
  }], function() {
    // logic after all the calls are completed.
  });
}

すべてのjQuery Ajaxリクエストが別の関数の中で処理されるまで関数を待機させるにはどうすればよいですか?

要するに、私は次の処理を実行する前に、すべてのAjaxリクエストが完了するのを待つ必要があります。 しかしどうですか?



jQueryは、この目的のためにwhen関数を定義するようになりまし

任意の数のDeferredオブジェクトを引数として受け取り、すべてが解決したら関数を実行します。

つまり、(たとえば)4つのAjaxリクエストを開始し、それが完了したらアクションを実行する場合は、次のようなことができます。

$.when(ajax1(), ajax2(), ajax3(), ajax4()).done(function(a1, a2, a3, a4){
    // the code here will be executed when all four ajax requests resolve.
    // a1, a2, a3 and a4 are lists of length 3 containing the response text,
    // status, and jqXHR object for each of the four ajax calls respectively.
});

function ajax1() {
    // NOTE:  This function must return the value 
    //        from calling the $.ajax() method.
    return $.ajax({
        url: "someUrl",
        dataType: "json",
        data:  yourJsonData,            
        ...
    });
}

私の意見では、それはきれいで明確な構文を作成し、ajaxStartやajaxStopなどのグローバル変数を必要とせず、ページの開発に際して望ましくない副作用を引き起こす可能性があります。

あなたが待たなければならない引数の数(引数の数を変えたい)をあらかじめ知っていなければ、それでもやりとりができますが、やや難解です。 $ .when()への遅延の配列を渡してください(多分引数の数を変えてトラブルシューティングをするときはjQueryです )。

ajaxスクリプトの失敗モードなどをより詳細に制御する必要がある場合は、 .when()によって返されたオブジェクトを保存することができます。元のajaxクエリをすべて網羅するjQuery Promiseオブジェクトです。 詳細な成功/失敗ハンドラを追加するには、 .then()または.fail()を呼び出すことができます。


javascriptはイベントベースなので、決して待つべきではなく 、フック/コールバックを設定する必要があります

あなたはおそらくjquery.ajax成功/完全なメソッドを使うことができます

または、 .ajaxComplete使用することもできます:

$('.log').ajaxComplete(function(e, xhr, settings) {
  if (settings.url == 'ajax/test.html') {
    $(this).text('Triggered ajaxComplete handler.');
    //and you can do whatever other processing here, including calling another function...
  }
});

あなたのAjaxリクエストがどのようにより正確に呼び出されているかの疑似コードを投稿する必要があります...


ajaxStopイベントを使用します。

たとえば、100個のAjaxリクエストを取得していて、 読み込んだメッセージを非表示にしたい場合は、 読み込み中のメッセージがあるとします。

jQueryの$.ajaxStopから:

$("#loading").ajaxStop(function() {
  $(this).hide();
});

そのページで行われているすべてのAjaxリクエストを待つことに注意してください。


注:上記の回答は、この回答が書かれた時点では存在しなかった機能を使用しています。 私はこれらのアプローチの代わりにjQuery.when()を使用することをお勧めしjQuery.when()が、私は歴史的な目的のために答えを残しています。

-

シンプルなカウントセマフォを使用すれば、コードを実装する方法はあなたのコードに依存しますが、おそらくそれを得ることができます。 簡単な例は、次のようなものです。

var semaphore  = 0,     // counting semaphore for ajax requests
    all_queued = false; // bool indicator to account for instances where the first request might finish before the second even starts

semaphore++;
$.get('ajax/test1.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

semaphore++;
$.get('ajax/test2.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

semaphore++;
$.get('ajax/test3.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

semaphore++;
$.get('ajax/test4.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

// now that all ajax requests are queued up, switch the bool to indicate it
all_queued = true;

これを{async:false}のように動作させたいがブラウザをロックしたくないのであれば、jQueryキューでも同じことができます。

var $queue = $("<div/>");
$queue.queue(function(){
    $.get('ajax/test1.html', function(data) {
        $queue.dequeue();
    });
}).queue(function(){
    $.get('ajax/test2.html', function(data) {
        $queue.dequeue();
    });
}).queue(function(){
    $.get('ajax/test3.html', function(data) {
        $queue.dequeue();
    });
}).queue(function(){
    $.get('ajax/test4.html', function(data) {
        $queue.dequeue();
    });
});

この方法を試してみてください。 ajax呼び出しが終了するまでJavaスクリプト関数内でループを作成します。

function getLabelById(id)
{
    var label = '';
    var done = false;
    $.ajax({
       cache: false,
       url: "YourMvcActionUrl",
       type: "GET",
       dataType: "json",
       async: false,
       error: function (result) {
         label='undefined';
         done = true;
        },
       success: function (result) {
            label = result.Message;
            done = true;
        }
     });

   //A loop to check done if ajax call is done.
   while (!done)
   {
      setTimeout(function(){ },500); // take a sleep.
   }

    return label;
}

すべてのAjaxロードが完了したらサイズチェックを使用しています

function get_ajax(link, data, callback) {
    $.ajax({
        url: link,
        type: "GET",
        data: data,
        dataType: "json",
        success: function (data, status, jqXHR) {
            callback(jqXHR.status, data)
        },
        error: function (jqXHR, status, err) {
            callback(jqXHR.status, jqXHR);
        },
        complete: function (jqXHR, status) {
        }
    })
}

function run_list_ajax(callback){
    var size=0;
    var max= 10;
    for (let index = 0; index < max; index++) {
        var link = 'http://api.jquery.com/ajaxStop/';
        var data={i:index}
        get_ajax(link,data,function(status, data){
            console.log(index)
            if(size>max-2){
                callback('done')
            }
            size++
            
        })
    }
}

run_list_ajax(function(info){
    console.log(info)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>


どれだけのAjaxリクエストがドキュメント内で終了するまで待つ場合は、どれくらいの数のAjaxリクエストが存在しても、 $.ajaxStopイベントをこの方法で使用して$.ajaxStop

  $(document).ajaxStop(function () {
      // 0 === $.active
  });

この場合、将来完了する可能性のあるアプリケーション内の要求数を推測する必要はありません。 場合によっては、ajaxリクエストは関数の内部ロジックの一部になることがあります(他の関数の呼び出しなど)。その場合、関数がそのロジックを待つのではなく、完了するためにajax部分。

ここの$.ajaxStopajaxによって変更されると思われるHTMLノードにバインドすることもできます。

このハンドラの目的は、何かをクリアまたはリセットしないアクティブな ajaxがいつ存在するかを知ることです。

PS ES6構文を使用しても構わない場合は、既知のajaxメソッドでPromise.allを使用できます。 例:

Promise.all([ajax1(), ajax2()]).then(() => {
 // all requests finished successfully
}).catch(() => {
 // all requests finished but one or more failed
})

ここで興味深い点は、 Promises$.ajaxリクエストの両方で$.ajaxすることです。 ここに最後のものを示すjsFiddleがあります。


また、 async.js使用することもできます。

私は、あなたがタイムアウト、SqlLiteコールなどのような約束をサポートしていない非同期呼び出しのすべての種類をマージすることができ、単なるajax要求ではなく、$。


単純なものが必要な場合。 一度コールバックを終了

        //multiple ajax calls above
        var callback = function () {
            if ($.active !== 0) {
                setTimeout(callback, '500');
                return;
            }
            //whatever you need to do here
            //...
        };
        callback();

私の解決策は次のとおりです

var request;
...
'services': {
  'GetAddressBookData': function() {
    //This is the primary service that loads all addressbook records 
    request = $.ajax({
      type: "POST",
      url: "Default.aspx/GetAddressBook",
      contentType: "application/json;",
      dataType: "json"
    });
  },

  ...

  'apps': {
    'AddressBook': {
      'data': "",
      'Start': function() {
          ...services.GetAddressBookData();
          request.done(function(response) {
            trace("ajax successful");
            ..apps.AddressBook.data = response['d'];
            ...apps.AddressBook.Filter();
          });
          request.fail(function(xhr, textStatus, errorThrown) {
            trace("ajax failed - " + errorThrown);
          });

非常にうまくいった。 私はこれを行うためのさまざまな方法を試しましたが、私はこれが最もシンプルで再利用可能であることを発見しました。 それが役に立てば幸い


私はgnarfによって私が探していた正確には私の自己によって良い答えを見つけました:)

jQuery ajaxQueue

//This handles the queues    
(function($) {

  var ajaxQueue = $({});

  $.ajaxQueue = function(ajaxOpts) {

    var oldComplete = ajaxOpts.complete;

    ajaxQueue.queue(function(next) {

      ajaxOpts.complete = function() {
        if (oldComplete) oldComplete.apply(this, arguments);

        next();
      };

      $.ajax(ajaxOpts);
    });
  };

})(jQuery);

次に、ajaxリクエストを次のようにキューに追加できます。

$.ajaxQueue({
        url: 'page.php',
        data: {id: 1},
        type: 'POST',
        success: function(data) {
            $('#status').html(data);
        }
    });







ajax