JQuery'nin eşzamansız bir Ajax isteği yerine eşzamanlı çalışmasını nasıl sağlayabilirim?


1208

Standart uzantı noktaları sağlayan bir JavaScript widget'ım var. Bunlardan biri beforecreatefonksiyon. falseBir öğenin oluşturulmasını önlemek için geri dönmelidir .

JQuery kullanarak bu işleve bir Ajax çağrısı ekledim:

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

Ancak widget'ımın öğeyi oluşturmasını önlemek istiyorum, bu yüzden falsegeri aramada değil, anne işlevinde dönmeliyim . JQuery veya başka bir tarayıcı içi API kullanarak senkronize bir AJAX isteği gerçekleştirmenin bir yolu var mı?


30
Bunu çözmenin uygun yolu, widget'ınızın uzantı noktası kullanım vaatlerini yeniden yazmak olacaktır. Bu şekilde, (ajax isteği gibi) olarak eşzamansız bir işlem ayarlamanıza olanak tanır beforecreate.
Kos

3
Sajak fonksiyonunu öneriyorum. T harfimiz var mı? Evet vanna, bana 3 T ver.
Cody O'Dell

2
@Kos yerinde. Eşitleme XHR burada gerekli değildir
Michael Westcott

1
İnsanlar javascript'i başlatırken bana 1 parça tavsiye istiyorlarsa, diyorum: javascript'in asenkron karakterini kucaklayın, bununla savaşmayı denemeyin.
Emmanuel Gecikmesi

3
Bu soru "Kullanıcı şifrelerimi düz metinde nasıl saklayabilirim?" Elbette bir cevap var, ama yapma.
Vectorjohn

Yanıtlar:


1165

Gönderen jQuery belgelerine : Belirttiğiniz asenkron hareket etme seçeneği yanlış bir senkron Ajax isteği alır. Ardından geri çağrınız ana işleviniz ilerlemeden önce bazı verileri ayarlayabilir.

Önerilen şekilde değiştirilirse kodunuzun nasıl görüneceği aşağıda açıklanmıştır:

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

97
Tam olarak, senkron çağrılar için get (), post (), load () kullanmak imkansızdır. Yalnızca ajax () öğesi "false" olarak ayarlanabilen "async" parametresine sahiptir.
SLA80

39
@ SLA80 Hayır. JQuery 1.1'den beri: stackoverflow.com/questions/6849686/…
StuperUser

16
@ qualidafial Yorumum SLA80'in yanlış yorumunu hedefliyor; senkron çağrılar için get (), post (), load () kullanmak mümkündür.
StuperUser

9
async false, jQuery> = 1.8 için artık desteklenmemektedir. Bakınız api.jquery.com/jQuery.ajax
ken

22
@ken async: falsehala jQuery> = 1.8'de desteklenmektedir. async: falseJqXHR ( $.Deferred) ile kullanma yeteneği kullanımdan kaldırılmıştır. Başka bir deyişle, eski yöntemler yerine, örneğin yeni başarı / hata / tam geri arama seçeneklerini kullanmak gerekir jqXHR.done().
Ben Johnson

255

JQuery'nin Ajax kurulumunu eşzamanlı moda getirerek

jQuery.ajaxSetup({async:false});

Ardından Ajax çağrılarınızı jQuery.get( ... );

Sonra sadece bir kez daha açın

jQuery.ajaxSetup({async:true});

Sanırım @Adam tarafından önerilenle aynı şekilde çalışıyor, ancak yeniden yapılandırmak isteyen birine jQuery.get()veya jQuery.post()daha ayrıntılı jQuery.ajax()sözdizimine yardımcı olabilir.


56
Bu gerçekten kötü bir fikir, neden küresel bir seviyeye yerleştirdin? Ve sonra onu unset etmek zorunda kalacak?
Juan Mendes

11
En azından, bu en iyi kötü fikir. "HİÇBİR ZAMAN YOKTUR" demek yerine $.ajax(). ;)
Rzassar

136

Mükemmel çözüm! Uygulamayı denediğimde başarı fıkrasında bir değer döndürürsem tanımsız olarak geri döndüğünü fark ettim. Bir değişkende saklamak ve bu değişkeni döndürmek zorunda kaldım. Bu benim geldi yöntemi:

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

16
Bunun nedeni, geri arama değerinin dışında bir değer döndürüyordunuz getWhatever. Böylece dönen hiçbir şey ie undefinedhesabınızla ilgili getWhatever.
Orbit'te Hafiflik Yarışları

6
bu kesinlikle yanlış. 'StrReturn' öğesini döndürürken eşzamansız bir çağrının tamamlandığından emin olamazsınız.
Thomas Fritz

61
Bu bir Eşzamanlı çağrıdır (eşzamansız: yanlış).
James in Indy

85

Tüm bu cevaplar, async: false ile bir Ajax çağrısı yapmanın, Ajax isteği tamamlanana kadar tarayıcının askıya alınmasına neden olacağı noktasını kaçırır. Akış denetimi kitaplığı kullanmak, tarayıcıyı kapatmadan bu sorunu çözecektir. Frame.js ile ilgili bir örnek :

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

4
Bir REST arka ucu için hızlı bir test kayışını bir araya getirmek istiyorsanız ve geri arama cehennemine göre sadeliği tercih ediyorsanız, senkron çağrılar kullanışlıdır.
Distortum

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


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

10
Yine de şunu elde edebilirsiniz: 'Son iş parçacığının zararlı etkileri nedeniyle ana iş parçasındaki Senkron XMLHttpRequest kullanımdan kaldırılmıştır.'
Hari

5
@ Ana iplik olmadan jQuery kullanarak senkronize bir ajax çağrısı yapmanın yolu nedir?
Jose Nobile

7
Bu cevabın sunacağı bir şey olduğunu görmüyorum, sadece bir fonksiyona sarılmış ve dört yıl sonra cevaplanan kabul edilen cevap. İnsanlara C + P'ye tavsiyede bulunmak kötü bir şeydir, çünkü işlev ne yaptığını göstermez. "Peki getURLvs get? Neden tarayıcımı asıyor?" vb.
moopet

27

Not: async: falseBu uyarı mesajları nedeniyle kullanmamalısınız :

Gecko 30.0'dan (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27) başlayarak, kullanıcı deneyiminin olumsuz etkileri nedeniyle ana iş parçacığında senkron istekleri kullanımdan kaldırıldı.

Chrome, konsolda bunun hakkında bile uyarıyor:

Ana iş parçasındaki zaman uyumlu XMLHttpRequest, son kullanıcının deneyimine zararlı etkileri nedeniyle kullanımdan kaldırılmıştır. Daha fazla yardım için https://xhr.spec.whatwg.org/ adresini ziyaret edin .

Böyle bir şey yapıyorsanız sayfanızı kırabilir, çünkü her gün çalışmayı durdurabilir.

Eşzamanlı ama yine de engellemiyor gibi hissettiren bir şekilde yapmak istiyorsanız, async / await ve muhtemelen yeni gibi vaatlere dayanan bazı ajax kullanmalısınız. Fetch API

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

Düzenle Chrome'u sayfa işten çıkarılmasında senkronizasyon XHR'sine izin vermeme üzerinde çalışıyor , sayfa kullanıcı tarafından gezinilirken veya kapatılırken sayfa kapatılmasında . Bu, yükleme öncesi, boşaltma, sayfa gizleme ve görünürlük değişimini içerir.

bu sizin kullanım durumunuzsa navigator.sendBeacon'a göz atmak isteyebilirsiniz bunun yerine

Sayfanın http üstbilgileri veya iframe'in izin verme özelliğiyle eşitleme gereksinimini devre dışı bırakması da mümkündür


Eşzamansız hataları yakalamak için await fetch(url)çağrınızı bir try... catchblokta sarmanız gerektiğini unutmayın .
inostia

4
foo işlevi asyncbaşlangıçta sadece sözcüğü kullanarak bir söze dönüştürüldü , bu yüzden foo().catch(...)onu da yakalamak için yapabilirsin
Endless

Chrome, ajax iç sayfa zaman uyumsuz izin verilmeyen beforeunloadama sonra olumsuz geribildirim sonra değişiklik geri döndürüldü bugs.chromium.org/p/chromium/issues/detail?id=952452
Alex

26

Alanlar arası bir Ajax çağrısı ( JSONP kullanarak ) yapıyorsanız , bunu eşzamanlı olarak yapamayacağınızı, asyncbayrağın jQuery tarafından yok sayılacağını unutmayın.

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

JSONP çağrıları için şunları kullanabilirsiniz:

  1. Kendi alan adınıza Ajax çağrısı yapın ve alanlar arası çağrı sunucu tarafını yapın
  2. Kodunuzu eşzamansız olarak çalışacak şekilde değiştirin
  3. Frame.js gibi bir "işlev sıralayıcı" kitaplığı kullanın (bu yanıt )
  4. Yürütmeyi engellemek yerine kullanıcı arayüzünü engelle (bu yanıt ) (en sevdiğim yol)

12

Sizinle birlikte async: falseengellenmiş bir tarayıcı olsun. Engellemeyen bir senkron çözüm için aşağıdakileri kullanabilirsiniz:

ES6 / ECMAScript2015

ES6 ile bir jeneratör ve ortak kütüphane kullanabilirsiniz :

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

ES7 ile asyc'i bekleyebilirsiniz:

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

3
Kendi kendine çağrılan async functionasenkron beforecreate: async function(....fonksiyonunu yeniden oluşturmak ve kaldırmak için geçebilirsiniz
Daniel Krom

12

Carcione tarafından verilen cevabı kullandım ve JSON kullanmak için değiştirdim.

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

Eklediğim dataType ait 'JSON' ve değiştirilemez .responseText için responseJSON .

Ayrıca , döndürülen nesnenin statusText özelliğini kullanarak durumu aldım . Bunun JSON'un geçerli olup olmadığını değil, Ajax yanıtının durumu olduğunu unutmayın.

Arka uç yanıtı doğru (iyi biçimlendirilmiş) JSON olarak döndürmelidir, aksi takdirde döndürülen nesne tanımsız olur.

Orijinal soruyu cevaplarken dikkate alınması gereken iki husus vardır. Biri Ajax'a senkronize çalışmasını söylüyor (zaman uyumsuz: false ayarlayarak ) ve diğeri yanıtı geri arama işlevine değil, çağıran işlevin dönüş deyimi aracılığıyla döndürüyor.

Ayrıca POST ile denedim ve çalıştı.

GET'i POST olarak değiştirdim ve veri ekledim : 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;
}

Yukarıdaki kod yalnızca durumda çalıştığını Not zaman uyumsuz olduğu yanlış . Async: true ayarlayacak olsaydınız , döndürülen nesne jqxhr , AJAX çağrısı döndüğünde geçerli olmaz, ancak daha sonra eşzamansız çağrı bittiğinde, ancak yanıt değişkenini ayarlamak için çok geç olur .


7

Bu örnek:

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

1
async falseSöz tabanlı bir çözümle kullanmanın anlamı nedir . Bu, tarayıcıyı hiçbir faydası olmadan kilitler.
Gitti Kodlama

2
@GoneCoding, kodu tam sırayla yürütmek istediğiniz durumlar var, bu durumda async false'u kullanabiliriz
Nikki

1
@Nikki: Kesinlikle sıralı olarak çalıştırmanın yolu bu değil . Async vaatlerini ( ajaxçağrılar zaten geri döner) ve .then()veya done()(zaten gösterildiği gibi) kullanın. Tarayıcıyı kilitlemek çok kötü bir kullanıcı deneyimidir. Dediğim gibi async: falsebu örnekte olmak tam bir zaman kaybıdır.
Kodlama Gone

4

Öncelikle $ .ajax'ı ne zaman ve $ .get / $.

İstek başlığı ayarları, önbellek ayarları, eşzamanlı ayarlar vb.

$ .get / $. post: ajax isteği üzerinde düşük seviye kontrol gerektirmediğimizde, sadece basit veri almak / sunucuya gönderin. Kestirme

$.ajax({
  url: url,
  data: data,
  success: success,
  dataType: dataType
});

dolayısıyla $ .get / $. post ile diğer özellikleri (senkronizasyon, önbellek vb.) kullanamayız.

Bu nedenle ajax isteği üzerinde düşük seviye kontrolü (senkronizasyon, önbellek vb.) İçin $ .ajax

 $.ajax({
     type: 'GET',
      url: url,
      data: data,
      success: success,
      dataType: dataType,
      async:false
    });

2

Bu benim jQuery ile ASYNC istekleri için basit bir uygulama. Umarım bu herkese yardım eder.

var queueUrlsForRemove = [
    'http://dev-myurl.com/image/1', 
    'http://dev-myurl.com/image/2',
    'http://dev-myurl.com/image/3',
];

var queueImagesDelete = function(){

    deleteImage( queueUrlsForRemove.splice(0,1), function(){
        if (queueUrlsForRemove.length > 0) {
            queueImagesDelete();
        }
    });

}

var deleteImage = function(url, callback) {
    $.ajax({
        url: url,
        method: 'DELETE'
    }).done(function(response){
        typeof(callback) == 'function' ? callback(response) : null;
    });
}

queueImagesDelete();

2

Çünkü XMLHttpReponsesenkron çalışma kullanımdan kaldırılmıştır ben tamamladı olduğunu şu çözüm geldi XMLHttpRequest. Bu, sıradan AJAX sorgularının doğada hala asikron olmasına rağmen, tek kullanımlık CSRF tokenleri için çok yararlıdır.

Ayrıca şeffaftır, böylece jQuery gibi kütüphaneler sorunsuz çalışır.

/* wrap XMLHttpRequest for synchronous operation */
var XHRQueue = [];
var _XMLHttpRequest = XMLHttpRequest;
XMLHttpRequest = function()
{
  var xhr   = new _XMLHttpRequest();
  var _send = xhr.send;

  xhr.send = function()
  {
    /* queue the request, and if it's the first, process it */
    XHRQueue.push([this, arguments]);
    if (XHRQueue.length == 1)
      this.processQueue();
  };

  xhr.processQueue = function()
  {
    var call = XHRQueue[0];
    var xhr  = call[0];
    var args = call[1];

    /* you could also set a CSRF token header here */

    /* send the request */
    _send.apply(xhr, args);
  };

  xhr.addEventListener('load', function(e)
  {
    /* you could also retrieve a CSRF token header here */

    /* remove the completed request and if there is more, trigger the next */
    XHRQueue.shift();
    if (XHRQueue.length)
      this.processQueue();
  });

  return xhr;
};

-1

Orijinal soru üzereyken yana jQuery.get, bu (belirtildiği gibi burada belirtmekte yarar var burada ) bir olabilir kullanmak async: falsebir de $.get()ama ideal önlemek asenkron beri XMLHTTPRequestkullanım dışı kalmıştır (ve tarayıcı bir uyarı verebilir):

$.get({
  url: url,// mandatory
  data: data,
  success: success,
  dataType: dataType,
  async:false // to make it synchronous
});

1
bu neden reddedildi?
alias51

-2

asyn:falseEşzamanlı hale getirmek için ajax isteğinde ayarlayın .

İşte kod örneği:

 $.ajax({
    url: 'some_url',
    type: "GET",
    async: false,
    cache: false,
    dataType: "JSON",
    data: { 
      "p1": v1, 
      "p2": v2
    },
    success: function(result) {
    }  
  }
});

Bu, ekranı yanıt vermeyebilir.

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.