Pertanyaan Bagaimana saya bisa mendapatkan jQuery untuk melakukan permintaan yang sinkron, bukan asynchronous, Ajax?


Saya memiliki widget JavaScript yang memberikan poin ekstensi standar. Salah satunya adalah beforecreate fungsi. Itu harus kembali false untuk mencegah item dibuat.

Saya telah menambahkan panggilan Ajax ke fungsi ini menggunakan jQuery:

beforecreate: function (node, targetNode, type, to) {
  jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),

  function (result) {
    if (result.isOk == false) 
        alert(result.message);
  });
}

Tetapi saya ingin mencegah widget saya membuat item, jadi saya harus kembali false dalam fungsi ibu, tidak dalam panggilan balik. Apakah ada cara untuk melakukan permintaan AJAX yang sinkron menggunakan jQuery atau API di-browser lainnya?


1050
2017-09-25 13:26


asal


Jawaban:


Dari dokumentasi jQuery: Anda tentukan asynchronous pilihan untuk menjadi Salah untuk mendapatkan permintaan Ajax yang sinkron. Kemudian callback Anda dapat mengatur beberapa data sebelum fungsi induk Anda diproses.

Seperti inilah tampilan kode Anda jika diubah seperti yang disarankan:

beforecreate: function (node, targetNode, type, to) {
    jQuery.ajax({
        url: 'http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
        success: function (result) {
            if (result.isOk == false) alert(result.message);
        },
        async: false
    });
}

1032
2017-09-25 13:30



Anda dapat menempatkan pengaturan Ajax jQuery dalam mode sinkron dengan menelepon

jQuery.ajaxSetup({async:false});

Dan kemudian lakukan panggilan Ajax Anda menggunakan jQuery.get( ... );

Kemudian hidupkan sekali lagi

jQuery.ajaxSetup({async:true});

Saya kira itu bekerja hal yang sama seperti yang disarankan oleh @Adam, tetapi mungkin bermanfaat untuk seseorang yang ingin mengkonfigurasi ulang mereka jQuery.get() atau jQuery.post() ke yang lebih rumit jQuery.ajax() sintaksis.


237
2018-04-12 21:45



Solusi bagus! Saya perhatikan ketika saya mencoba untuk menerapkannya bahwa jika saya mengembalikan nilai dalam klausul keberhasilan, itu kembali sebagai tidak terdefinisi. Saya harus menyimpannya dalam sebuah variabel dan mengembalikan variabel itu. Ini adalah metode yang saya dapatkan:

function getWhatever() {
  // strUrl is whatever URL you need to call
  var strUrl = "", strReturn = "";

  jQuery.ajax({
    url: strUrl,
    success: function(html) {
      strReturn = html;
    },
    async:false
  });

  return strReturn;
}

125
2018-04-07 13:30



Semua jawaban ini kehilangan titik yang melakukan panggilan Ajax dengan async: false akan menyebabkan browser hang sampai permintaan Ajax selesai. Menggunakan pustaka kontrol aliran akan menyelesaikan masalah ini tanpa menggantung browser. Berikut ini contohnya dengan Frame.js:

beforecreate: function(node,targetNode,type,to) {

    Frame(function(next)){

        jQuery.get('http://example.com/catalog/create/', next);
    });

    Frame(function(next, response)){

        alert(response);
        next();
    });

    Frame.init();
}

82
2018-04-28 17:41



function getURL(url){
    return $.ajax({
        type: "GET",
        url: url,
        cache: false,
        async: false
    }).responseText;
}


//example use
var msg=getURL("message.php");
alert(msg);

49
2018-04-25 15:34



Perlu diingat bahwa jika Anda melakukan panggilan Ajax lintas domain (dengan menggunakan JSONP) - kamu tidak bisa melakukannya secara sinkron, async Bendera akan diabaikan oleh jQuery.

$.ajax({
    url: "testserver.php",
    dataType: 'jsonp', // jsonp
    async: false //IGNORED!!
});

Untuk panggilan JSONP, Anda dapat menggunakan:

  1. Ajax-call ke domain Anda sendiri - dan lakukan sisi server lintas-domain call
  2. Ubah kode Anda untuk bekerja secara asinkron
  3. Gunakan perpustakaan "fungsi sequencer" seperti Frame.js (ini menjawab)
  4. Blokir UI bukannya memblokir eksekusi (ini menjawab) (cara favorit saya)

22
2018-05-10 06:28



Catatan: Anda tidak seharusnya menggunakan async karena ini:

Dimulai dengan Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), permintaan sinkron pada utas utama telah dihentikan karena efek negatif pada pengalaman pengguna.

Chrome bahkan memperingatkan tentang ini di konsol:

Synchronous XMLHttpRequest pada utas utama tidak lagi digunakan karena efeknya yang merusak pada pengalaman pengguna akhir. Untuk bantuan lebih lanjut, periksa https://xhr.spec.whatwg.org/.

Ini dapat merusak halaman Anda jika Anda melakukan sesuatu seperti ini karena bisa berhenti bekerja setiap hari.

Jika Anda ingin melakukannya dengan cara yang masih terasa seperti jika itu sinkron tetapi masih tidak memblokir maka Anda harus menggunakan async / menunggu dan mungkin juga beberapa ajax yang didasarkan pada janji-janji seperti yang baru Mengambil API

async function foo() {
  var res = await fetch(url)
  console.log(res.ok)
  var json = await res.json()
  console.log(json)
}

17
2017-12-13 12:55



Dengan async: false Anda mendapatkan peramban yang diblokir. Untuk solusi sinkron yang tidak memblokir, Anda dapat menggunakan yang berikut:

ES6 / ECMAScript2015

Dengan ES6 Anda dapat menggunakan generator & perpustakaan co:

beforecreate: function (node, targetNode, type, to) {
    co(function*(){  
        let result = yield jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
        //Just use the result here
    });
}

ES7

Dengan ES7 Anda bisa menggunakan asyc waiting:

beforecreate: function (node, targetNode, type, to) {
    (async function(){
        let result = await jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
        //Just use the result here
    })(); 
}

9
2017-08-20 19:52



Saya menggunakan jawaban yang diberikan oleh Carcione dan memodifikasinya untuk menggunakan JSON.

 function getUrlJsonSync(url){

    var jqxhr = $.ajax({
        type: "GET",
        url: url,
        dataType: 'json',
        cache: false,
        async: false
    });

    // 'async' has to be 'false' for this to work
    var response = {valid: jqxhr.statusText,  data: jqxhr.responseJSON};

    return response;
}    

function testGetUrlJsonSync()
{
    var reply = getUrlJsonSync("myurl");

    if (reply.valid == 'OK')
    {
        console.dir(reply.data);
    }
    else
    {
        alert('not valid');
    }    
}

Saya menambahkan tipe data dari 'JSON' dan mengubah .responseText untuk responsJSON.

Saya juga mengambil status menggunakan statusText milik objek yang dikembalikan. Perhatikan, bahwa ini adalah status respons Ajax, bukan apakah JSON valid.

Back-end harus mengembalikan respon dalam JSON yang benar (well-formed), jika tidak objek yang dikembalikan akan tidak terdefinisi.

Ada dua aspek yang perlu dipertimbangkan ketika menjawab pertanyaan asli. Salah satunya mengatakan Ajax untuk melakukan serentak (dengan pengaturan async: salah) dan yang lainnya mengembalikan respons melalui pernyataan balik fungsi panggilan, alih-alih ke fungsi panggilan balik.

Saya juga mencobanya dengan POST dan itu berhasil.

Saya mengubah GET menjadi POST dan menambahkan data: postdata

function postUrlJsonSync(url, postdata){

    var jqxhr = $.ajax({
        type: "POST",
        url: url,
        data: postdata,
        dataType: 'json',
        cache: false,
        async: false
    });

    // 'async' has to be 'false' for this to work
    var response = {valid: jqxhr.statusText,  data: jqxhr.responseJSON};

    return response;
}

Perhatikan bahwa kode di atas hanya berfungsi dalam kasus di mana async aku s Salah. Jika Anda ingin mengatur async: true objek yang dikembalikan jqxhr tidak akan berlaku pada saat panggilan AJAX kembali, hanya nanti ketika panggilan asynchronous selesai, tapi itu sudah terlalu terlambat untuk mengatur tanggapan variabel.


8
2017-11-15 11:33



Ini adalah contoh:

$.ajax({
  url: "test.html",
  async: false
}).done(function(data) {
   // Todo something..
}).fail(function(xhr)  {
   // Todo something..
});

6
2017-08-16 13:20