Tunggu sampai semua permintaan jQuery Ajax selesai?

675

Bagaimana cara membuat fungsi menunggu sampai semua permintaan jQuery Ajax dilakukan di dalam fungsi lain?

Singkatnya, saya harus menunggu semua permintaan Ajax selesai sebelum saya menjalankan selanjutnya. Tapi bagaimana caranya?

jamietelin
sumber
Bagaimana Anda memanggil permintaan ajax asli Anda?
NakedBrunch
2
Apa yang Anda maksud dengan "selesai"? Saya memahaminya sebagai "semua permintaan telah berhasil atau tidak selesai" (diselesaikan atau ditolak). Tetapi Anda dapat berarti "semua permintaan telah selesai dengan sukses" (diselesaikan). lihat semua variasi di api.jquery.com/category/deferred-object
Adrien Be

Jawaban:

911

jQuery sekarang mendefinisikan fungsi when untuk tujuan ini.

Ia menerima sejumlah objek yang ditangguhkan sebagai argumen, dan menjalankan fungsi ketika semuanya diselesaikan.

Itu berarti, jika Anda ingin memulai (misalnya) empat permintaan ajax, kemudian melakukan tindakan ketika selesai, Anda dapat melakukan sesuatu seperti ini:

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

Menurut pendapat saya, itu membuat sintaksis yang bersih dan jelas, dan menghindari melibatkan variabel global seperti ajaxStart dan ajaxStop, yang bisa memiliki efek samping yang tidak diinginkan saat halaman Anda berkembang.

Jika Anda tidak tahu sebelumnya berapa banyak argumen ajax yang harus Anda tunggu (yaitu Anda ingin menggunakan sejumlah variabel argumen), itu masih bisa dilakukan tetapi hanya sedikit lebih rumit. Lihat Menyerahkan array dari Ditangguhkan ke $ .when () (dan mungkin jQuery .when memecahkan masalah dengan jumlah variabel argumen ).

Jika Anda memerlukan kontrol lebih dalam atas mode kegagalan skrip ajax dll., Anda dapat menyimpan objek yang dikembalikan oleh .when()- itu adalah objek jQuery Promise yang mencakup semua kueri ajax asli. Anda dapat memanggil .then()atau .fail()menambahkannya ke penangan sukses / kegagalan yang terperinci.

Alex
sumber
46
Ini harus ditandai sebagai jawaban yang benar karena itu sederhana, efisien dan berfungsi dengan baik. Juga, harus dicatat bahwa $.whenmengembalikan Promiseobjek yang memiliki metode yang lebih bermanfaat, tidak hanya .done. Misalnya, dengan .then(onSuccess, onFailure)metode Anda dapat bereaksi ketika kedua permintaan berhasil atau setidaknya salah satu dari mereka gagal.
skalee
2
Apakah mungkin untuk mengelompokkan permintaan ajax1..4 ke dalam array dan meneruskannya?
andig
33
Hati-hati dengan failkopernya. Tidak seperti done, failkebakaran segera pada kegagalan pertama dan mengabaikan sisa tangguhan.
Ryan Mohr
1
@skalee terima kasih karena telah menyoroti fakta bahwa suatu onFailurefungsi dapat dilampirkan. Seperti yang saya tunjukkan dalam komentar pada pertanyaan OP: dia mungkin ingin menunjukkan lebih tepatnya apa yang dia maksud dengan "selesai". "Ryan Mohr" juga memiliki poin yang sangat bagus mengenai fakta yang failberperilaku berbeda done, beberapa bacaan lebih lanjut harus dilakukanPromises saya kira html5rocks.com/en/tutorials/es6/promises
Adrien Be
1
Sangat bagus untuk memberi orang paparan metode kapan, dan janji secara umum, tapi saya pikir ini bukan jawaban terbaik. Jika salah satu dari fungsi ajax mana saja di telepon membuat permintaan ajax lain, dan kemudian tidak mengintegrasikan janji baru itu ke dalam rantai dengan benar ... permintaan tersebut akan lolos dari teknik ini. Sebagai contoh, saya tidak dapat menggunakan teknik ini tanpa memodifikasi perpustakaan Shopify yang saya gunakan untuk perilaku ajax add-to-cart, karena itu tidak ditulis dengan cara yang 'menjanjikan', dan tidak pernah mengembalikan objek xhr yang dibuatnya. Apakah ini masuk akal? Masih jawaban yang bagus!
Ziggy
292

Jika Anda ingin tahu kapan semua ajax permintaan selesai di dokumen Anda, tidak peduli berapa banyak dari mereka ada, cukup gunakan $ .ajaxStop acara dengan cara ini:

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

Dalam hal ini, Anda tidak perlu menebak berapa banyak permintaan yang terjadi dalam aplikasi, yang mungkin selesai di masa depan, atau menggali logika fungsi kompleks atau menemukan fungsi mana yang melakukan HTTP(S)permintaan.

$.ajaxStopdi sini juga dapat terikat ke HTMLsimpul apa pun yang menurut Anda mungkin dimodifikasi oleh requst.


Pembaruan:
Jika Anda ingin tetap menggunakan ESsintaks, maka Anda dapat menggunakan Promise.all untuk ajaxmetode yang diketahui :

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

Hal yang menarik di sini adalah bahwa ia berfungsi baik dengan Promisesdan $.ajaxmeminta.

Ini adalah demonstrasi jsFiddle .


Pembaruan 2:
Namun versi yang lebih baru menggunakan async / menunggu sintaks :

try {
  const results = await Promise.all([ajax1(), ajax2()])
  // do other actions
} catch(ex) { }
Arsen Khachaturyan
sumber
16
+1 Jauh lebih baik daripada jawaban lain jika Anda harus berurusan dengan skrip pihak ke-3 dengan panggilan balik / anonim.
kaiser
5
@kaiser Poin yang valid tapi bukan itu pertanyaannya. Ini tidak terlalu baik jika Anda tidak ingin menunggu semua panggilan AJAX kembali. Pertanyaannya khusus tentang menunggu panggilan AJAX yang Anda buat sendiri (disebut di dalam fungsi lain, seperti yang ditulis OP). Beberapa kode lain mungkin telah membuat panggilan AJAX lain yang tidak ingin Anda tunggu.
Juan Mendes
6
Dibandingkan dengan solusi when (), ia memiliki keuntungan untuk bekerja bahkan jika jumlah panggilan ajax tidak diketahui.
Alexis Dufrenoy
5
Dibandingkan dengan solusi when (), ia memiliki kelemahan besar untuk tidak bekerja dengan baik bersama dengan komponen lain, karena ia berbagi negara global dengan dokumen yang luas. Jika ada pemungutan suara panjang yang berlangsung terus menerus, itu mungkin bahkan tidak pernah menyala.
Bergi
3
Anda tidak benar @AdrienBe, ajaxStop menangani semua permintaan ajax tidak peduli apakah mereka berhasil atau tidak, sama seperti bukti dari kata-kata saya lihat jsfiddle.net/36votxba/2
Arsen Khachaturyan
32

Saya menemukan jawaban yang bagus oleh gnarf diri saya yang persis seperti yang saya cari :)

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

Kemudian Anda dapat menambahkan permintaan ajax ke antrian seperti ini:

$.ajaxQueue({
        url: 'page.php',
        data: {id: 1},
        type: 'POST',
        success: function(data) {
            $('#status').html(data);
        }
    });
jamietelin
sumber
37
Sepertinya Anda lupa memberikan atribusi yang tepat untuk jawaban ini , saya telah menambahkannya.
Pos Tim
21

Gunakan ajaxStopacara tersebut.

Sebagai contoh, katakanlah Anda memiliki pesan memuat ... sambil mengambil 100 permintaan ajax dan Anda ingin menyembunyikan pesan itu sekali dimuat.

Dari dokumen jQuery :

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

Perhatikan bahwa itu akan menunggu semua permintaan ajax dilakukan pada halaman itu.

Olafure
sumber
5
Ini mengasumsikan bahwa Anda tahu tidak akan ada permintaan AJAX lain di halaman, bukan asumsi yang sangat bagus
Juan Mendes
Pada jQuery 1.8, metode .ajaxStop () hanya boleh dilampirkan ke dokumen.
Geomorillo
1
Perbaiki saya jika saya salah, tetapi bukankah ini akan mengubah proyek Anda menjadi situs "formulir web sekolah lama"? Maksud saya jika Anda seluruh halaman Anda harus menunggu permintaan sebelum itu dapat dilanjutkan maka apa gunanya permintaan ajax di tempat pertama?
BillRuhl
@ BillRuhl dalam kasus kami, saya mengulang-ulang koleksi jquery untuk membangun hal-hal baru dan perlu tahu tentang seluruh koleksi ketika selesai, sebelum membuat beberapa penyesuaian tata letak. Sepertinya bukan kasus yang tidak biasa. Akan buruk jika sekelompok barang ajax lainnya mungkin sedang dalam proses, tetapi tidak akan, di sini.
eon
21

CATATAN: Jawaban di atas menggunakan fungsionalitas yang tidak ada pada saat jawaban ini ditulis. Saya merekomendasikan penggunaan jQuery.when()daripada pendekatan ini, tetapi saya meninggalkan jawaban untuk tujuan historis.

-

Anda mungkin bisa bertahan dengan semaphore penghitungan sederhana, meskipun bagaimana Anda menerapkannya akan tergantung pada kode Anda. Contoh sederhana akan menjadi seperti ...

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;

Jika Anda ingin ini beroperasi seperti {async: false} tetapi Anda tidak ingin mengunci browser, Anda bisa melakukan hal yang sama dengan antrian 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();
    });
});
BBonifield
sumber
10
Sepertinya ini akan terlalu memperumit masalah sepele.
Chris
2
Benar-benar tidak terlalu rumit. Menghitung semaphore adalah mekanisme umum dalam CS. Jika Anda lebih suka, contoh menggunakan antrian jQuery akan bekerja dengan baik tanpa harus mengimplementasikan semaphore sendiri.
BBonifield
1
Saya tidak melihat masalah dengan penghitung semaphore, namun, saya melihat masalah dengan gagasan memiliki fungsi EMPAT untuk menangani panggilan balik yang dihasilkan. Anda harus mendefinisikan suatu fungsi terlebih dahulu, kemudian referensi fungsi itu di masing-masing .get(). Dengan begitu setidaknya Anda tidak menggandakan kode itu. Tidak hanya itu tetapi menyatakan function(){}setiap waktu mengalokasikan memori setiap kali! Agak praktik yang buruk jika Anda bisa memanggil fungsi yang ditentukan secara statis.
Alexis Wilke
1
@AlexisWilke Ini adalah jawaban 4,5 tahun, dan itu dimaksudkan untuk menjadi contoh bagaimana semaphores dan antrian bekerja. Anda berpikir terlalu keras tentang hal ini, dan saya tidak berpikir KAPITALISASI UNTUK MEMBUAT POINT diperlukan.
BBonifield
2
Yah ... Saya bukan orang yang memberi Anda -1 ... dan saya mengerti bahwa jawaban cenderung menua. Namun, orang-orang terus menemukan mereka dan sejauh yang saya tahu tidak dilarang untuk memberikan info kepada orang-orang yang berpotensi memanfaatkannya hingga hari ini.
Alexis Wilke
8

javascript berbasis acara, jadi Anda tidak boleh menunggu , lebih baik mengatur kait / panggilan balik

Anda mungkin bisa menggunakan metode sukses / lengkap dari jquery.ajax

Atau Anda bisa menggunakan .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...
  }
});

meskipun Anda harus memposting kode semu tentang bagaimana permintaan ajax Anda dipanggil lebih tepat ...

Stefano
sumber
8

Solusi kecil adalah sesuatu seperti ini:

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

Semoga bisa bermanfaat ...

Jesfre
sumber
Sementara jawaban lainnya secara teknis lebih baik karena lebih mudah dimengerti, saya sangat suka yang ini. Bagus!
Jay
4

jQuery memungkinkan Anda menentukan apakah Anda ingin permintaan ajax tidak sinkron atau tidak. Anda cukup membuat ajax permintaan sinkron dan kemudian sisa kode tidak akan dijalankan sampai mereka kembali.

Sebagai contoh:

jQuery.ajax({ 
    async: false,
    //code
});
shmuel613
sumber
42
Satu hal yang perlu diperhatikan adalah menggunakan {async: false} dapat sementara mengunci browser. api.jquery.com/jQuery.ajax
BBonifield
30
Ini berjalan bertentangan dengan praktik standar jQuery / Javascript. AJAX selalu dianggap asinkron. Anda harus menggunakan jQuery.when () sebagai gantinya.
SystemParadox
43
Itu ide yang sangat buruk! Tidak pernah melakukannya! Memblokir = tidak menanggapi tindakan pengguna sama sekali, bahkan untuk menggulir atau apa pun! (Juga, async: false akan ditinggalkan dalam jQuery 1.8.)
skalee
5
Khususnya jika permintaan gagal atau butuh waktu lama untuk alasan yang tidak dapat diprediksi (yang, menurut Hukum Murphy, pasti akan terjadi!), Ini biasanya merupakan ide yang buruk untuk kode produksi karena penguncian browser seperti yang disebutkan di atas.
Alex
27
Ini adalah ide yang sangat buruk. JANGAN GUNAKAN JAWABAN INI.
Tauren
2

Jika Anda membutuhkan sesuatu yang sederhana; sekali dan dilakukan panggilan balik

        //multiple ajax calls above
        var callback = function () {
            if ($.active !== 0) {
                setTimeout(callback, '500');
                return;
            }
            //whatever you need to do here
            //...
        };
        callback();
Fatmuemoo
sumber
4
itu dapat menghasilkan loop tanpa akhir!
Diego Favero
2
Ini adalah loop tanpa akhir? Kapan? Kapan AJAX tidak pernah kembali?
Jonathan
2

Anda juga dapat menggunakan async.js .

Saya pikir ini lebih baik daripada $ .Ketika karena Anda dapat menggabungkan semua jenis panggilan asinkron yang tidak mendukung janji di luar kotak seperti batas waktu, panggilan SqlLite dll, dan bukan hanya permintaan ajax.

George Mavritsakis
sumber
2

Atas dasar jawaban @BBonifield, saya menulis fungsi utilitas sehingga logika semaphore tidak menyebar di semua panggilan ajax.

untilAjax adalah fungsi utilitas yang memanggil fungsi panggilan balik ketika semua panggilan ajax selesai.

ajaxObjsadalah array dari objek pengaturan ajax [http://api.jquery.com/jQuery.ajax/].

fn adalah fungsi callback

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

Contoh: doSomethingfungsi menggunakan 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.
  });
}
Sanjeev Kumar Dangi
sumber
2

Saya sangat merekomendasikan menggunakan $ .when () jika Anda memulai dari awal.

Meskipun pertanyaan ini memiliki lebih dari jutaan jawaban, saya masih tidak menemukan sesuatu yang berguna untuk kasus saya. Katakanlah Anda harus berurusan dengan basis kode yang ada, sudah melakukan beberapa panggilan ajax dan tidak ingin memperkenalkan kompleksitas janji dan / atau mengulang semuanya.

Kita dapat dengan mudah memanfaatkan jQuery .data, .ondan .triggerfungsi yang telah menjadi bagian dari jQuery sejak selamanya.

Codepen

Hal baik tentang solusi saya adalah:

  • sudah jelas apa yang sebenarnya bergantung pada callback

  • fungsi triggerNowOrOnLoadedtidak peduli jika data telah dimuat atau kami masih menunggu untuk itu

  • sangat mudah untuk menghubungkannya ke kode yang sudah ada

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

cilf
sumber
2

Saya menggunakan pemeriksaan ukuran ketika semua beban ajax selesai

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>

tranchau
sumber
jempol ke teladan Anda.
MarwaAhmad
2

Untuk memperluas jawaban Alex, saya punya contoh dengan argumen dan janji variabel. Saya ingin memuat gambar melalui ajax dan menampilkannya di halaman setelah semuanya dimuat.

Untuk melakukan itu, saya menggunakan yang berikut:

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

Diperbarui untuk bekerja baik untuk url tunggal atau ganda: https://jsfiddle.net/euypj5w9/

GammaGames
sumber
2

Seperti jawaban lain yang disebutkan, Anda dapat menggunakan ajaxStop()untuk menunggu sampai semua permintaan ajax selesai.

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

Jika Anda ingin melakukannya untuk ajax()permintaan tertentu , yang terbaik yang dapat Anda lakukan adalah menggunakan complete()metode di dalam permintaan ajax tertentu:

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


Tapi, jika Anda hanya perlu menunggu beberapa permintaan ajax dan pasti dilakukan? Gunakan janji javascript yang luar biasa untuk menunggu sampai ajax yang ingin Anda tunggu selesai. Saya membuat contoh singkat, mudah dan mudah dibaca untuk menunjukkan kepada Anda bagaimana cara kerja janji dengan ajax.
Silakan lihat contoh berikut . Saya biasa setTimeoutmengklarifikasi contoh.

// 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>

Peselancar perak
sumber
0

Saya menemukan cara sederhana, menggunakan 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
uingtea
sumber
0

Solusi saya adalah sebagai berikut

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

Bekerja dengan cukup baik. Saya sudah mencoba banyak cara berbeda untuk melakukan ini, tetapi saya menemukan ini sebagai yang paling sederhana dan paling dapat digunakan kembali. Semoga ini bisa membantu

Eric Sean Moore
sumber
0

Lihatlah solusi saya:

1. Masukkan fungsi ini (dan variabel) ke file javascript Anda:

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. Buat array dengan permintaan Anda, seperti ini:

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.Create fungsi callback:

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

4. Panggil fungsi runFunctionQueue dengan parameter:

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

Coba dengan cara ini. buat loop di dalam fungsi skrip java untuk menunggu sampai panggilan ajax selesai.

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;
}
ChinaHelloWorld
sumber
1
Anda setTimeout()TIDAK take a sleep. Dalam hal ini, Anda hanya memblokir semua tab hingga donemenjadi benar.
Alexis Wilke
1
Saya pikir ini adalah topik yang menanyakan: "Tunggu sampai semua permintaan jQuery Ajax selesai".
ChinaHelloWorld
1
Sudahkah Anda menguji kode ini? harapan saya adalah bahwa donetidak akan pernah benar ketika loop sementara masih berjalan. Jika loop sementara sedang berjalan, loop peristiwa tidak dapat dilanjutkan dan oleh karena itu tidak akan pernah menjalankan panggilan balik ke keberhasilan ajax.
Kevin B