javascript - success - jqxhr




等到所有jQuery Ajax請求完成? (12)

Alex給出的解決方案工作正常。 相同的概念,但以一種不同的方式使用它(當呼叫數目未預先知道時)

http://garbageoverflow.blogspot.com/2014/02/wait-for-n-or-multiple-or-unknown.html

我如何讓一個函數等到所有jQuery Ajax請求在另一個函數內完成?

簡而言之,在執行下一步之前,我需要等待所有的Ajax請求完成。 但是如何?


jQuery允許你指定你是否希望ajax請求是異步的。 您可以簡單地使ajax請求同步,然後其他代碼將不會執行,直到它們返回。

例如:

jQuery.ajax({ 
    async: false,
    //code
});

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...
  }
});

儘管你應該發布一個偽代碼,說明你的(s)ajax請求如何被更精確地調用。


注意:上面的答案使用了在撰寫此答案時不存在的功能。 我建議使用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();
    });
});

你也可以使用async.js

我認為它比$更合適,因為你可以合併所有類型的異步調用,例如超時,SqlLite調用等,而不僅僅是ajax請求。


使用ajaxStop事件。

例如,假設您在獲取100個Ajax請求時有加載...消息,並且您想在加載後隱藏該消息。

從jQuery $.ajaxStop

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

請注意,它將等待該頁面上所有的Ajax請求。


如果你從頭開始,我強烈建議使用$.when() 。

即使這個問題有超過百萬的答案,我仍然沒有發現對我的案例有用。 假設您必須處理現有的代碼庫,已經做出了一些Ajax調用,並且不想介紹承諾的複雜性和/或重做整個事情。

我們可以很容易地利用jQuery .data.on.trigger函數,它們一直是jQuery的一部分。

Codepen

關於我的解決方案的好東西是:

  • 很明顯回調確切依賴於什麼

  • triggerNowOrOnLoaded函數不關心數據是否已經被加載,或者我們還在等待它

  • 將其插入現有代碼非常容易

$(function() {

  // wait for posts to be loaded
  triggerNowOrOnLoaded("posts", function() {
    var $body = $("body");
    var posts = $body.data("posts");

    $body.append("<div>Posts: " + posts.length + "</div>");
  });


  // some ajax requests
  $.getJSON("https://jsonplaceholder.typicode.com/posts", function(data) {
    $("body").data("posts", data).trigger("posts");
  });

  // doesn't matter if the `triggerNowOrOnLoaded` is called after or before the actual requests 
  $.getJSON("https://jsonplaceholder.typicode.com/users", function(data) {
    $("body").data("users", data).trigger("users");
  });


  // wait for both types
  triggerNowOrOnLoaded(["posts", "users"], function() {
    var $body = $("body");
    var posts = $body.data("posts");
    var users = $body.data("users");

    $body.append("<div>Posts: " + posts.length + " and Users: " + users.length + "</div>");
  });

  // works even if everything has already loaded!
  setTimeout(function() {

    // triggers immediately since users have been already loaded
    triggerNowOrOnLoaded("users", function() {
      var $body = $("body");
      var users = $body.data("users");

      $body.append("<div>Delayed Users: " + users.length + "</div>");
    });

  }, 2000); // 2 seconds

});

// helper function
function triggerNowOrOnLoaded(types, callback) {
  types = $.isArray(types) ? types : [types];

  var $body = $("body");

  var waitForTypes = [];
  $.each(types, function(i, type) {

    if (typeof $body.data(type) === 'undefined') {
      waitForTypes.push(type);
    }
  });

  var isDataReady = waitForTypes.length === 0;
  if (isDataReady) {
    callback();
    return;
  }

  // wait for the last type and run this function again for the rest of the types
  var waitFor = waitForTypes.pop();
  $body.on(waitFor, function() {
    // remove event handler - we only want the stuff triggered once
    $body.off(waitFor);

    triggerNowOrOnLoaded(waitForTypes, callback);
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body>Hi!</body>


如果你需要簡單的東西, 一次並完成回調

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

我找到簡單的方法,它使用shift()

function waitReq(id)
{
  jQuery.ajax(
  {
    type: 'POST',
    url: ajaxurl,
    data:
    {
      "page": id
    },
    success: function(resp)
    {
      ...........
      // check array length if not "0" continue to use next array value
      if(ids.length)
      {
        waitReq(ids.shift()); // 2
      )
    },
    error: function(resp)
    {
      ....................
      if(ids.length)
      {
        waitReq(ids.shift());
      )
    }
  });
}

var ids = [1, 2, 3, 4, 5];    
// shift() = delete first array value (then print)
waitReq(ids.shift()); // print 1

我的解決方案如下

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);
          });

工作得很好。 我嘗試了很多不同的方式來做到這一點,但我發現這是最簡單和最可重用的。 希望能幫助到你



看看我的解決方案:

1.將此函數(和變量)插入到您的JavaScript文件中:

var runFunctionQueue_callback;

function runFunctionQueue(f, index, callback) {

  var next_index = index + 1

  if (callback !== undefined) runFunctionQueue_callback = callback;

  if (f[next_index] !== undefined) {
    console.log(index + ' Next function avalaible -> ' + next_index);
    $.ajax({
      type: 'GET',
      url: f[index].file,
      data: (f[index].data),
      complete: function() {
        runFunctionQueue(f, next_index);
      }
    });
  } else {
    console.log(index + ' Last function');
    $.ajax({
      type: 'GET',
      url: f[index].file,
      data: (f[index].data),
      async: false,
      complete: runFunctionQueue_callback
    });
  }
}

2.根據您的請求構建一個數組,如下所示:

var f = [
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}}
        ];

3.創建回調函數:

function Function_callback() {
  alert('done');
}

4.使用參數調用runFunctionQueue函數:

runFunctionQueue(f, 0, QuestionInsert_callback);
// first parameter: array with requests data
// second parameter: start from first request
// third parameter: the callback function




ajax