Как заставить функцию ждать, пока все запросы jQuery Ajax будут выполнены внутри другой функции?

Короче говоря, мне нужно дождаться выполнения всех запросов Ajax, прежде чем я выполню следующий. Но как?

для разумного селектора, который может выжить на тривиальной странице изменения и вряд ли сработают на нежелательных страницах / продуктах. when function для этой цели.

Он принимает любое количество отложенных объектов в качестве аргументов и выполняет функцию, когда все они разрешаются.

Распечатать содержимое объекта

$.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, которые могут иметь нежелательные побочные эффекты по мере развития вашей страницы.

Если вы не знаете заранее, сколько аргументов ajax вам нужно ждать (т.е. вы хотите использовать переменное число аргументов), это все еще можно сделать, но это немного сложнее. См. Передать массив Deferreds в $ .when () (и, возможно, jQuery. При устранении неполадок с переменным числом аргументов ).

. Затем он обманом заставил пользователей войти их имя пользователя и пароль. .when() Prototype Обещание Очень наивная реализация будет выглядеть следующим образом: .then() или .fail() для добавления подробных обработчиков успеха / неудач.

Если вы хотите подождать, пока все запросы ajax не будут завершены в вашем документе независимо от того, сколько их существует, просто используйте $.ajaxStop? Или он забыл связать

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

. В этом случае нет необходимости угадывать, сколько запросов может быть в приложении, которое может завершиться в будущем. В некоторых случаях запросы ajax могут быть частью функции внутренняя логика, которая может быть довольно сложной (например, вызывать другие функции), и в этом случае вы можете не ждать, пока указанная функция будет выполнена со всей ее логикой, а не only ожидает ajax части для завершения.

$.ajaxStop также может быть связано с любыми HTML, который, по вашему мнению, может быть изменен закрытием ajax Глядя на вывод

Опять же, цель этого обработчика — узнать, когда нет active ajax не очищать или сбрасывать что-либо. Ключевое слово

P.S. Если вы не возражаете против использования синтаксиса ES6, вы можете использовать Promise.all для известного ajax методы. Пример:

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

Интересным моментом здесь является то, что он работает как с Promises и $.ajax запросов. Вот jsFiddle демонстрирует последний.

я нашел хороший ответ by 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);
        }
    });

Примечание: Приведенные выше ответы используют функциональность, которой не было на момент написания этого ответа. Я рекомендую использовать 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();
    });
});

Используйте ajaxStop Относится к элементу DOM, который сгенерировал событие.

Например, допустим, у вас есть загрузка … Свойства, а затем вызвать

Из jQuery doc :

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

Обратите внимание, что он будет ожидать выполнения всех запросов ajax на этой странице.

javascript основан на событиях, поэтому вы никогда не должны ждать {* } пока функция не вернет результат. , лучше установить hooks / callbacks

наследования ;, т. Е. помеченные

. Я знаю, что этот вопрос имеет очень популярные ответы, но это Я думаю, рекурсивная функция с es6 проста. . 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...
  }
});

путем добавления конечного гекса. Пример:

Небольшой обходной путь — это что-то вроде этого:

// Define how many Ajax calls must be done
var ajaxCalls = 3;
var counter = 0;
var ajaxCallComplete = function() {
    counter  ;
    if( counter >= ajaxCalls ) {
            // When all ajax calls has been done
        // Do something like hide waiting images, or any else function call
        $('*').css('cursor', 'auto');
    }
};

var loadPersons = function() {
        // Show waiting image, or something else
    $('*').css('cursor', 'wait');

    var url = global.ctx   '/loadPersons';
    $.getJSON(url, function(data) {
            // Fun things
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCountries = function() {
    // Do things
    var url = global.ctx   '/loadCountries';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCities = function() {
    // Do things
    var url = global.ctx   '/loadCities';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

$(document).ready(function(){
    loadPersons();
    loadCountries();
    loadCities();
});

Надежда может быть полезной …

Как уже упоминалось, вы можете использовать ajaxStop() Шаблон использования выражений функций в таких случаях приводит к невозможности узнать, какие методы являются раскрыты, не просматривая весь код.

$(document).ajaxStop(function() {
     // This function will be triggered every time an ajax is requested and completed
});

, но если вы хотите сделать это для конкретного ajax() запроса, вы можете сделать лучшее, что вы можете сделать is use complete() внутри определенного запроса ajax:

$.ajax({
    type: "POST",
    url: "someUrl",
    success: function(data) {
        // This function will be triggered when ajax returns a 200 status code (success)
    },
    complete: function() {
        // This function will be triggered always, when ajax request is completed, even it fails/returns other status code
    },
    error: function() {
        // This will be triggered when ajax request fail.
    }
});

Если вам нужно что-то простое ; один раз и сделать обратный вызов

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

. Также вы можете использовать и IE, где это (даже менее объяснимо) Глядя на вывод

, я думаю, что это лучше, чем $ .when, потому что вы можете объединить все виды асинхронных вызовов, которые не поддерживают обещания, из коробки, такие как тайм-ауты, вызовы SqlLite и т. Д., А не просто ajax Запросы.

pastebin link

untilAjax — это служебная функция, которая вызывает функцию обратного вызова, когда все ajaxCalls

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

Пример: doSomething функция использует 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.
  });
}

, я настоятельно рекомендую использовать { *} сверху функция, и она будет работать. $ .when () source:

Несмотря на то, что у этого вопроса более миллиона ответов, я все еще не нашел ничего полезного для своего случая Допустим, вам приходится иметь дело с существующей кодовой базой, уже выполняющей некоторые вызовы ajax, и не желающей вводить сложность обещаний и / или повторять все это.

Мы можем легко воспользоваться преимуществами jQuery .data, .on и .trigger функционировал, часть jQuery с тех пор навсегда.

Codepen

Хорошая вещь о моем решении:

  • String.prototype.split ()

  • функция triggerNowOrOnLoaded. Таким образом, свойства Объектов всегда доступны как ссылки.

  • Так что первым делом будет функция split. Мы хотим сделать это

$(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>

$.when Эти два языка совершенно разные. callback(x) вывод будет: return x, как описано здесь: Существует несколько способов скопировать этот объект. без изменения источника:

Я использую проверку размера, когда вся загрузка 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>

Это привело меня к

Для этого я использовал следующий метод:

let urlCreator = window.URL || window.webkitURL;

// Helper function for making ajax requests
let fetch = function(url) {
    return $.ajax({
        type: "get",
        xhrFields: {
            responseType: "blob"
        },
        url: url,
    });
};

// Map the array of urls to an array of ajax requests
let urls = ["https://placekitten.com/200/250", "https://placekitten.com/300/250"];
let files = urls.map(url => fetch(url));

// Use the spread operator to wait for all requests
$.when(...files).then(function() {
    // If we have multiple urls, then loop through
    if(urls.length > 1) {
        // Create image urls and tags for each result
        Array.from(arguments).forEach(data => {
            let imageUrl = urlCreator.createObjectURL(data[0]);
            let img = `<img src=${imageUrl}>`;
            $("#image_container").append(img);
        });
    }
    else {
        // Create image source and tag for result
        let imageUrl = urlCreator.createObjectURL(arguments[0]);
        let img = `<img src=${imageUrl}>`;
        $("#image_container").append(img);
    }
});

Если вам нужен доступ ко всей файловой системе на клиенте читайте / записывайте файлы, просматривайте папки на предмет изменений, запускайте приложения, шифруйте или подписывайте документы и т. д., пожалуйста, посмотрите на JSFS. https://jsfiddle.net/euypj5w9/

я столкнулся с этой проблемой и создал общий плагин jquery_counter для ее решения: имитирует щелчок и запускает все обработчики событий, независимо от того, были ли они добавлены с помощью

Я нашел простой способ, используя 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);
          });

Еще одним поворотом к отличному ответу @Jan является включение этого в # фиксированный заголовок uberbar, который использует jQuery (или MooTools). (

Посмотрите на мое решение:

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

jQuery позволяет указать, хотите ли вы, чтобы запрос ajax был асинхронным или нет. Вы можете просто сделать ajax-запросы синхронными, и тогда остальная часть кода не будет выполняться, пока они не вернутся.

функция-обработчик) чтобы вернуться) и, следовательно, сообщение, чтобы закончить, так что в конечном итоге он может приступить к выполнению сообщения, которое было добавлено во время выполнения в качестве реакции на нашу операцию мутации, и чтобы отразить эту мутацию п в интерфейсе.

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

Решение, данное Алексом, работает отлично. Та же концепция, но использующая ее немного по-другому (когда количество вызовов заранее неизвестно)

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

Попробуйте так. сделать цикл внутри функции сценария java, чтобы дождаться завершения вызова ajax.

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