Tüm jQuery Ajax istekleri tamamlanana kadar bekleyin?


675

Tüm jQuery Ajax istekleri başka bir işlev içinde yapılana kadar bir işlevi nasıl bekleyebilirim?

Kısacası, bir sonraki yürütmeden önce tüm Ajax isteklerinin yapılmasını beklemem gerekiyor. Ama nasıl?


Orijinal ajax isteklerinizi nasıl çağırıyorsunuz?
NakedBrunch

2
"Tamam" ile ne demek istiyorsun? Bunu "tüm isteklerin başarıyla tamamlanıp tamamlanmadığını" (çözülmüş veya reddedilmiş) olarak anlıyorum. Ancak "tüm istekler başarıyla tamamlandı" (çözümlendi) anlamına gelebilir. api.jquery.com/category/deferred-object adresindeki
Adrien Be

Yanıtlar:


911

jQuery şimdi bu amaçla bir when işlevi tanımlar .

Herhangi bir sayıda Ertelenmiş nesneyi bağımsız değişken olarak kabul eder ve hepsi çözüldüğünde bir işlevi yürütür.

Bu, örneğin dört ajax isteği başlatmak (örneğin), ardından tamamlandığında bir eylem gerçekleştirmek istiyorsanız, şöyle bir şey yapabilirsiniz:

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

Kanımca, temiz ve açık bir sözdizimi sağlar ve sayfanız geliştikçe istenmeyen yan etkilere sahip olabilecek ajaxStart ve ajaxStop gibi global değişkenleri dahil etmekten kaçınır.

Kaç tane ajax argümanı beklemeniz gerektiğini önceden bilmiyorsanız (yani, değişken sayıda argüman kullanmak istiyorsanız), yine de yapılabilir, ancak biraz daha karmaşıktır. Bkz . Deferreds dizisini $ .when () öğesine (ve belki de değişken sayıda argümanla sorun giderirken jQuery .

Ajax betiklerinin vb. Hata modları üzerinde daha derin kontrole ihtiyacınız varsa, döndürülen nesneyi kaydedebilirsiniz .when()- bu , tüm orijinal ajax sorgularını kapsayan bir jQuery Promise nesnesidir. Ayrıntılı başarı / başarısızlık işleyicileri eklemek için .then()veya .fail()üzerinde arama yapabilirsiniz .


46
Bu doğru bir cevap olarak işaretlenmelidir çünkü basit, verimli ve harika çalışır. Ayrıca, sadece yararlı olmayan yöntemlere sahip $.whenbir Promisenesneyi döndürdüğüne dikkat edilmelidir .done. Örneğin, .then(onSuccess, onFailure)yöntemle, her iki istek de başarılı olduğunda veya en az biri başarısız olduğunda yanıt verebilirsiniz.
skalee

2
Ajax1..4 isteklerini bir diziye gruplamak ve iletmek mümkün mü?
andig

33
failDavaya dikkat edin . Bunun aksine done, faililk başarısızlık anında ateşler ve kalan ertelemeleri göz ardı eder.
Ryan Mohr

1
@skalee bir onFailurefonksiyonun eklenebileceğini vurguladığınız için teşekkürler . OP'nin sorusuna yaptığı bir yorumda belirttiğim gibi: "bitti" ile ne demek istediğini daha kesin olarak belirtmek isteyebilir. "Ryan Mohr" da failfarklı davranan gerçeği ile ilgili çok iyi bir noktaya sahipti, sanırım html5rocks.com/en/tutorials/es6/promisesdone hakkında yapılması gereken bazı okumalarPromises
Adrien Be

1
İnsanlara when metoduna maruz kalma ve genel olarak vaatlerde bulunmak harika, ama bence bu en iyi cevap değil. Satırın herhangi bir yerinde bu ajax işlevlerinden herhangi biri başka bir ajax isteği oluşturursa ve daha sonra bu yeni vaadi zincire doğru bir şekilde entegre etmezse ... bu istekler bu teknikten kaçacaktır. Örneğin, ajax sepete ekle davranışı için kullandığım Shopify kütüphanesini değiştirmeden bu tekniği kullanamıyorum çünkü 'promisy' bir şekilde yazılmadı ve asla oluşturduğu xhr nesnelerini döndürmedi. Bu mantıklı mı? Yine de harika bir cevap!
Ziggy

292

Kaç tane istek olursa olsun, belgenizdeki tüm ajax isteklerin ne zaman tamamlandığını bilmek istiyorsanız , $ .ajaxStop olayını şu şekilde kullanın:

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

Bu durumda, uygulamada ne kadar istek gerçekleştiğini, gelecekte bitirilebileceğini tahmin etmeniz veya karmaşık mantık işlevlerine girmeniz veya hangi işlevlerin HTTP(S)istek yaptığını bulmanız gerekmez .

$.ajaxStopburada HTMLrequst tarafından değiştirilebileceğini düşündüğünüz herhangi bir düğüme de bağlanabilir .


Güncelleme:
Eğer sopa ile isterseniz ESsözdizimi, o zaman kullanabilirsiniz Promise.all bilinen için ajaxyöntemlere:

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

Burada ilginç olan nokta, her iki çalışmasıdır Promisesve $.ajaxistekleri.

İşte jsFiddle gösterisi.


Güncelleme 2: Async / await sözdizimini
kullanan daha yeni bir sürüm :

try {
  const results = await Promise.all([ajax1(), ajax2()])
  // do other actions
} catch(ex) { }

16
+1 Anonim geri aramalar / kapanışlarla 3. taraf komut dosyalarıyla uğraşmanız durumunda diğer yanıtlardan çok daha iyi .
kaiser

5
@kaiser Geçerli nokta, ancak sorunun sorduğu şey bu değildi. Tüm AJAX çağrılarının geri dönmesini beklemek istemiyorsanız çok iyi değil. Soru, kendi başınıza yaptığınız AJAX çağrılarını beklemekle ilgilidir (OP'nin yazdığı gibi başka bir fonksiyonun içinde denir). Başka bir kod, beklemek istemediğiniz başka bir AJAX çağrısı yapmış olabilir.
Juan Mendes

6
When () çözümüyle karşılaştırıldığında, ajax çağrılarının sayısı bilinmese bile çalışmanın avantajı vardır.
Alexis Dufrenoy

5
When () çözümüyle karşılaştırıldığında, belge genelinde küresel bir durumu paylaştığı için diğer bileşenlerle birlikte iyi çalışmamak büyük dezavantaja sahiptir. Sürekli devam eden uzun bir oylama varsa, asla ateşlenmeyebilir.
Bergi

3
Doğru değilsiniz @AdrienBe, ajaxStop, başarılı olsun ya da olmasın, tüm ajax isteklerini işler, tıpkı sözlerimin kanıtı olarak bu jsfiddle.net/36votxba/2
Arsen Khachaturyan

32

Ben buldum iyi bir cevap ile gnarf tam olarak aradığım şey olan :)

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

Ardından kuyruğa şu şekilde bir ajax isteği ekleyebilirsiniz:

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

37
Bu cevaba uygun atıfta bulunmayı unuttuğunuz anlaşılıyor, ben de ekledim.
Tim Post

21

ajaxStopEtkinliği kullanın .

Örneğin, 100 ajax isteği getirilirken bir yükleme ... mesajınız olduğunu ve yüklendikten sonra bu mesajı gizlemek istediğinizi varsayalım.

JQuery belgesinden :

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

Bu sayfada yapılan tüm ajax isteklerinin bekleyeceğini unutmayın.


5
Bu, sayfada başka bir AJAX isteği olmayacağını bildiğinizi varsayar, çok iyi bir varsayım değildir
Juan Mendes

JQuery 1.8'den itibaren .ajaxStop () yöntemi yalnızca belgeye eklenmelidir.
Geomorillo

1
Yanlışsam beni düzeltin ama bu projenizi bir "eski okul web formları" sitesine dönüştürmeyecek mi? Demek istediğim, sayfanızın devam edebilmesi için bir istek beklemesi gerekiyorsa, ilk etapta ajax isteğinin anlamı nedir?
BillRuhl

@BillRuhl bizim durumumuzda, yeni şeyler oluşturmak için bir jquery koleksiyonuna giriyorum ve bazı düzen ayarlamaları yapmadan önce tüm koleksiyon hakkında bilgi sahibi olmalıyım. Özellikle alışılmadık bir durum gibi görünmüyor. Eğer bir sürü diğer ajax malzeme işlemde olabilir, ama burada olmayacak, kötü olurdu.
eon

21

NOT: Yukarıdaki yanıtlar, bu yanıtın yazıldığı sırada mevcut olmayan işlevleri kullanır. jQuery.when()Bu yaklaşımlar yerine kullanılmasını öneriyorum ama cevabı tarihsel amaçlar için bırakıyorum.

-

Muhtemelen basit bir sayma semaforu ile başarabilirsiniz, ancak nasıl uyguladığınız kodunuza bağlı olacaktır. Basit bir örnek ...

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;

Bunun {async: false} gibi çalışmasını istiyorsanız, ancak tarayıcıyı kilitlemek istemediyseniz, aynı şeyi bir jQuery kuyruğuyla da başarabilirsiniz.

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

10
Bu önemsiz bir sorunu aşırı derecede karmaşık hale getirecek gibi görünüyor.
Chris

2
Gerçekten o kadar da karmaşık değil. Semaforları saymak CS'de yaygın bir mekanizmadır. Yine de, jQuery kuyruklarını kullanan örnek, semaforu kendiniz uygulamak zorunda kalmadan da işe yarayacaktır.
BBonifield

1
Semafor sayacı ile ilgili bir sorun görmüyorum, ancak ortaya çıkan geri aramayı işlemek için DÖRT fonksiyona sahip olma fikri ile ilgili bir sorun görüyorum. Önce bir işlev tanımlamalı, sonra her birinde bu işleve başvurmalısınız .get(). Bu şekilde en azından bu kodu çoğaltmazsınız. Sadece bu değil, function(){}her seferinde bildirmek her seferinde bellek ayırır! Statik olarak tanımlanmış bir işlev çağırabiliyorsanız oldukça kötü uygulama.
Alexis Wilke

1
@AlexisWilke Bu 4,5 yıllık bir cevap ve semaforların ve kuyrukların nasıl çalıştığına bir örnek olması gerekiyordu. Bu konuda biraz fazla zor düşünüyorsun ve bir nokta yapmak için büyük harf yapmanın gerekli olduğunu düşünmüyorum.
BBonifield

2
Şey ... Sana -1 veren biri değilim ... ve cevapların yaşlanma eğiliminde olduğunu anlıyorum. Yine de, insanlar onları bulmaya devam ediyor ve bildiğim kadarıyla bugün hala potansiyel olarak kullanacak insanlara bilgi vermek yasak değil.
Alexis Wilke

8

javascript olay tabanlıdır, bu nedenle asla beklememelisiniz , kanca / geri arama ayarlamalısınız

Muhtemelen jquery.ajax'ın başarı / tam yöntemlerini kullanabilirsiniz.

Veya .ajaxComplete kullanabilirsiniz :

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

gerçi ajax istek (ler) inizin nasıl daha kesin olarak adlandırıldığına dair bir takma kod göndermelisiniz ...


8

Küçük bir çözüm şöyle:

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

Umut faydalı olabilir ...


Diğer cevaplar teknik olarak daha iyi olsa da, anlaşılması daha kolay olsa da, bunu gerçekten seviyorum. Güzel!
Jay

4

jQuery, ajax isteğinin eşzamansız olmasını isteyip istemediğinizi belirtmenize olanak tanır. Yalnızca ajax isteklerini senkronize edebilirsiniz ve kodun geri kalanı geri dönünceye kadar yürütülmez.

Örneğin:

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

42
Dikkat edilmesi gereken bir nokta, {async: false} kullanmanın tarayıcıyı geçici olarak kilitleyebileceğidir. api.jquery.com/jQuery.ajax
BBonifield

30
Bu, standart jQuery / Javascript uygulamasının tersine çalışır. AJAX'ın her zaman eşzamansız olması gerekir. Bunun yerine jQuery.when () kullanmalısınız.
SystemParadox

43
Bu çok kötü bir fikir! Bunu asla yapma! Engelleme = kaydırma veya herhangi bir şey için bile kullanıcı eylemlerine hiç yanıt vermiyor! (Ayrıca, async: false, jQuery 1.8'de kullanımdan kaldırılacak.)
skalee

5
Özellikle istek başarısız olursa veya öngörülemeyen bir nedenden ötürü uzun zaman alırsa (ki bu Murphy'nin Yasası ile gerçekleşmek zorundadır!), Bu genellikle yukarıda belirtildiği gibi tarayıcı kilitleme nedeniyle üretim kodu için kötü bir fikirdir.
Alex

27
Bu çok kötü bir fikir. BU CEVAP KULLANMAYIN.
Tauren

2

Basit bir şeye ihtiyacınız varsa; bir kez ve geri arama bitti

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

4
sonsuz bir döngü oluşturabilir!
Diego Favero

2
Bu sonsuz bir döngü mü? Ne zaman? AJAX asla geri dönmediğinde?
Jonathan

2

Ayrıca async.js kullanabilirsiniz .

Ben sadece $ .when zaman zaman ajax istekleri değil, zaman aşımları, SqlLite çağrıları vb gibi kutudan vaat desteklemiyor asenkron çağrı her türlü birleştirebilirsiniz çünkü daha iyi olduğunu düşünüyorum.


2

@BBonifield yanıtı temelinde, semafor mantığının tüm ajax çağrılarına yayılmaması için bir yardımcı program yazdım.

untilAjax tüm ajaxCall'lar tamamlandığında bir geri çağırma işlevi çağıran yardımcı program işlevidir.

ajaxObjsajax ayar nesneleri dizisidir [http://api.jquery.com/jQuery.ajax/].

fn geri arama işlevi

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

Örnek: doSomethingişlev kullanır 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.
  });
}

2

Sıfırdan başlıyorsanız $ .when () kullanmanızı tavsiye ederim .

Bu sorunun milyondan fazla yanıtı olmasına rağmen, davam için hala yararlı bir şey bulamadım. Diyelim ki, zaten bazı ajax çağrıları yapmak ve vaatlerin karmaşıklığını tanıtmak ve / veya her şeyi yeniden yapmak istemiyorsanız, mevcut bir kod tabanı ile uğraşmak zorundasınız.

Biz kolayca jQuery yararlanabilir .data, .onve .triggersonsuza beri jQuery bir parçası olmuştur fonksiyonları.

Codepen

Çözümümle ilgili iyi şeyler:

  • Geri aramanın tam olarak neye bağlı olduğu açıktır

  • işlev triggerNowOrOnLoaded, verilerin önceden yüklenmiş olup olmadığını umursamıyor veya hala bekliyoruz

  • mevcut bir koda takmak çok kolay

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


2

Tüm ajax yükü tamamlandığında boyut kontrolü kullanıyorum

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>


başparmak yukarıya örnek.
MarwaAhmad

2

Alex'in cevabını genişletmek için, değişken argümanları ve vaatleri olan bir örneğim var. Ajax aracılığıyla görüntüleri yüklemek ve hepsi yüklendikten sonra bunları sayfada görüntülemek istedim.

Bunu yapmak için aşağıdakileri kullandım:

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

Tek veya birden fazla URL'de çalışacak şekilde güncellendi: https://jsfiddle.net/euypj5w9/


2

Belirtilen diğer yanıtlar gibi, ajaxStop()tüm ajax isteği tamamlanana kadar beklemek için kullanabilirsiniz .

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

Belirli bir ajax()istek için yapmak istiyorsanız, yapabileceğiniz en iyi şey complete(), belirli ajax isteğinin içindeki yöntemi kullanmaktır :

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


Ancak, sadece birkaç ve bazı ajax isteğinin yapılması için beklemek gerekiyorsa? Beklemek istediğiniz bu ajax bitene kadar beklemek için harika javascript vaatlerini kullanın . Size vaatlerin ajax ile nasıl çalıştığını göstermek için kısa, kolay ve okunabilir bir örnek verdim.
Lütfen bir sonraki örneğe göz atın . Kullandığım setTimeoutörnek açıklamak.

// Note:
// resolve() is used to mark the promise as resolved
// reject() is used to mark the promise as rejected

$(document).ready(function() {
    $("button").on("click", function() {

        var ajax1 = new Promise((resolve, reject) => {
            $.ajax({
                type: "GET",
                url: "https://miro.medium.com/max/1200/0*UEtwA2ask7vQYW06.png",
                xhrFields: { responseType: 'blob'},
                success: function(data) {
                    setTimeout(function() {
                        $('#image1').attr("src", window.URL.createObjectURL(data));
                        resolve(" Promise ajax1 resolved");
                    }, 1000);
                },
                error: function() {
                    reject(" Promise ajax1 rejected");
                },
            });
        });

        var ajax2 = new Promise((resolve, reject) => {
            $.ajax({
                type: "GET",
                url: "https://cdn1.iconfinder.com/data/icons/social-media-vol-1-1/24/_github-512.png",
                xhrFields: { responseType: 'blob' },
                success: function(data) {
                    setTimeout(function() {
                         $('#image2').attr("src", window.URL.createObjectURL(data));
                         resolve(" Promise ajax2 resolved");
                    }, 1500);
                },
                error: function() {
                    reject(" Promise ajax2 rejected");
                },
            });
        });

        var ajax3 = new Promise((resolve, reject) => {
            $.ajax({
                type: "GET",
                url: "https://miro.medium.com/max/632/1*LUfpOf7teWvPdIPTBmYciA.png",
                xhrFields: { responseType: 'blob' },
                success: function(data) {
                    setTimeout(function() {
                         $('#image3').attr("src", window.URL.createObjectURL(data));
                         resolve(" Promise ajax3 resolved");
                    }, 2000);
                },
                error: function() {
                    reject(" Promise ajax3 rejected");
                },
            });
        });
        
        Promise.all([ajax1, ajax2, ajax3]).then(values => {
            console.log("We waited until ajax ended: " + values);
            console.log("My few ajax ended, lets do some things!!")
        }, reason => {
            console.log("Promises failed: " + reason);
        });
        
        // Or if you want wait for them individually do it like this
        // ajax1.then(values => {
        //    console.log("Promise 1 resolved: " + values)
        // }, reason => {
        //     console.log("Promise 1 failed: " + reason)
        // });
    });

});
img {
  max-width: 200px;
  max-height: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>Make AJAX request</button>
<div id="newContent">
    <img id="image1" src="">
    <img id="image2" src="">
    <img id="image3" src="">
</div>


0

Basit bir yol buldum, 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

0

Benim çözümüm aşağıdaki

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

Oldukça güzel çalıştı. Bunu yapmanın birçok farklı yolunu denedim, ama bunu en basit ve en yeniden kullanılabilir olarak buldum. Umarım yardımcı olur


0

Çözümüme bak:

Bu işlevi (ve değişkeni) javascript dosyanıza ekleyin:

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.İsteğiniz gibi bir dizi oluşturun:

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. geri arama fonksiyonu oluşturun:

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

4. runFunctionQueue işlevini parametrelerle arayın:

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


-4

Bu şekilde dene. ajax çağrısı bitene kadar beklemek için java script fonksiyonu içinde bir döngü yapın.

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

1
Sizin setTimeout()değil take a sleep. Bu durumda, donegerçek olana kadar tüm sekmeleri engellersiniz .
Alexis Wilke

1
Ben bu konuyu soran olduğunu düşünüyorum: "Tüm jQuery Ajax istekleri yapılana kadar bekleyin".
ChinaHelloWorld

1
Bu kodu test ettiniz mi? benim beklentim ise donewhile döngüsü devam ederken asla doğru olmayacak. While döngüsü çalışıyorsa, olay döngüsü devam edemez ve bu nedenle ajax başarısı için geri aramayı asla çalıştırmaz.
Kevin B
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.