JQuery'nin bir Ajax çağrısının geri dönmeden önce bitmesini nasıl bekleyebilirim?


244

Giriş gerektiren bir sunucu tarafı fonksiyonum var. Kullanıcı oturum açtıysa, işlev başarılı olursa 1 değerini döndürür. Değilse, işlev giriş sayfasına dönecektir.

Ajax ve jQuery kullanarak işlevi çağırmak istiyorum. Yaptığım şey, üzerine bir tıklama işlevi uygulanmış, sıradan bir bağlantı ile isteği göndermek. Kullanıcı oturum açmadıysa veya işlev başarısız olursa, Ajax çağrısının true değerini döndürmesini istiyorum, böylece href tetiklenir.

Ancak, aşağıdaki kodu kullandığımda, Ajax çağrısı yapılmadan önce işlev çıkar.

Kullanıcıyı nazikçe giriş sayfasına nasıl yönlendirebilirim?

$(".my_link").click(
    function(){
    $.ajax({
        url: $(this).attr('href'),
        type: 'GET',
        cache: false,
        timeout: 30000,
        error: function(){
            return true;
        },
        success: function(msg){ 
            if (parseFloat(msg)){
                return false;
            } else {
                return true;
            }
        }
    });
});

2
Eski bir iş parçacığı olabilir, ancak @kofifus async'i false olarak ayarlamanın kötü bir tasarım olduğunu ve "hiçbir zaman aşımı vb. İşlenmeyeceğini" belirtir. Bu basitleştirilmiş çözümü deneyebilir - stackoverflow.com/a/11576418/6937841
Shan

Yanıtlar:


357

$.ajax()İşlevin hemen geri dönmesini istemiyorsanız , asyncseçeneği şu şekilde ayarlayın false:

$(".my_link").click(
    function(){
    $.ajax({
        url: $(this).attr('href'),
        type: 'GET',
        async: false,
        cache: false,
        timeout: 30000,
        error: function(){
            return true;
        },
        success: function(msg){ 
            if (parseFloat(msg)){
                return false;
            } else {
                return true;
            }
        }
    });
});

Ancak, bunun AJAX noktasına karşı olacağını belirtmek isterim. Ayrıca, errorve successişlevlerindeki yanıtı ele almalısınız . Bu işlevler yalnızca sunucudan yanıt alındığında çağrılır.


10
Bence iyi uygulamaları gözden geçirmek yargılamıyor ve StackOverflow'daki en iyi cevaplardan bazılarının işareti.
semperos

68
Asla kullanmayın async: false. Tarayıcının olay döngüsü, güvenilir olmayan ağ G / Ç'sini beklerken kilitlenir. Her zaman daha iyi bir yol vardır. Bu durumda, bağlantının hedefi kullanıcı oturumunu ve 302'yi giriş sayfasına doğrulayabilir.
Matthew

3
Test async: falseiçin çok yararlı olabilir.
Jarrett

4
@Matthew Gerçekten mi? Kullanıcıyı başka bir sayfaya göndermeden veya yenilemeden önce zaman uyumsuz bir ajax göndermenin alternatifi nedir?
NoBugs

2
asyncdeğeri false, çoğu tarayıcı kullanımında kullanımdan kaldırılmıştır. Tarayıcıların daha yeni sürümlerinde istisnalar atabilir. Bkz. Xhr.spec.whatwg.org/#sync-warning ( jQuery kullanan asyncxhr openyöntemi parametresi için geçerlidir ).
Frédéric

42

Ben kullanmıyorum $.ajaxama $.postve $.getfonksiyonları, bu yüzden cevap beklemek gerekirse, ben bunu kullanın:

$.ajaxSetup({async: false});
$.get("...");

34

Temel alınan XMLHttpRequest nesnesi (istek yapmak için jQuery tarafından kullanılır) eşzamansız özelliği destekler. False değerine ayarlayın . Sevmek

async: false

24

Genellikle kötü tasarım olan async'i false olarak ayarlamak yerine, işlem beklemedeyken kullanıcı arayüzünü engellemeyi düşünebilirsiniz.

Bu, jQuery vaatleriyle aşağıdaki gibi güzel bir şekilde başarılabilir:

// same as $.ajax but settings can have a maskUI property
// if settings.maskUI==true, the UI will be blocked while ajax in progress
// if settings.maskUI is other than true, it's value will be used as the color value while bloking (i.e settings.maskUI='rgba(176,176,176,0.7)'
// in addition an hourglass is displayed while ajax in progress
function ajaxMaskUI(settings) {
    function maskPageOn(color) { // color can be ie. 'rgba(176,176,176,0.7)' or 'transparent'
        var div = $('#maskPageDiv');
        if (div.length === 0) {
            $(document.body).append('<div id="maskPageDiv" style="position:fixed;width:100%;height:100%;left:0;top:0;display:none"></div>'); // create it
            div = $('#maskPageDiv');
        }
        if (div.length !== 0) {
            div[0].style.zIndex = 2147483647;
            div[0].style.backgroundColor=color;
            div[0].style.display = 'inline';
        }
    }
    function maskPageOff() {
        var div = $('#maskPageDiv');
        if (div.length !== 0) {
            div[0].style.display = 'none';
            div[0].style.zIndex = 'auto';
        }
    }
    function hourglassOn() {
        if ($('style:contains("html.hourGlass")').length < 1) $('<style>').text('html.hourGlass, html.hourGlass * { cursor: wait !important; }').appendTo('head');
        $('html').addClass('hourGlass');
    }
    function hourglassOff() {
        $('html').removeClass('hourGlass');
    }

    if (settings.maskUI===true) settings.maskUI='transparent';

    if (!!settings.maskUI) {
        maskPageOn(settings.maskUI);
        hourglassOn();
    }

    var dfd = new $.Deferred();
    $.ajax(settings)
        .fail(function(jqXHR, textStatus, errorThrown) {
            if (!!settings.maskUI) {
                maskPageOff();
                hourglassOff();
            }
            dfd.reject(jqXHR, textStatus, errorThrown);
        }).done(function(data, textStatus, jqXHR) {
            if (!!settings.maskUI) {
                maskPageOff();
                hourglassOff();
            }
            dfd.resolve(data, textStatus, jqXHR);
        });

    return dfd.promise();
}

bununla artık şunları yapabilirsiniz:

ajaxMaskUI({
    url: url,
    maskUI: true // or try for example 'rgba(176,176,176,0.7)'
}).fail(function (jqXHR, textStatus, errorThrown) {
    console.log('error ' + textStatus);
}).done(function (data, textStatus, jqXHR) {
    console.log('success ' + JSON.stringify(data));
});

Ve arayüz, ajax komutu dönene kadar engellenir

bkz. jsfiddle


Async'i false olarak ayarlamak, tek bir kod satırı haricinde aynı şeyi yapmaz mı?
Vincent

4
Bir şey değil. Eşzamansız ayarı false olarak ayarlamak isteği eşzamansız hale getirir. Bu, geri dönene kadar işlemeyi durdurur; bu genellikle kötü bir uygulamadır, örneğin hiçbir olay, diğer ajax istekleri, zaman aşımları vb. Ajax işlerken (yani etkileyecek kısmı) kullanıcı arayüzünün yalnızca bir bölümünü engellemek için yukarıdaki kodu da değiştirebilirsiniz
kofifus

11

İşlerin Eğer kod eğer kolay olacağını düşünüyorum successdöndürmek yerine uygun sayfa yüklemeye fonksiyonunu trueveya false.

Örneğin, geri dönmek yerine trueşunları yapabilirsiniz:

window.location="appropriate page";

Bu şekilde başarı işlevi çağrıldığında sayfa yeniden yönlendirilir.


5

Modern JS'de async/ karakterini aşağıdaki awaitgibi kullanabilirsiniz :

  async function upload() {
    return new Promise((resolve, reject) => {
        $.ajax({
            url: $(this).attr('href'),
            type: 'GET',
            timeout: 30000,
            success: (response) => {
                resolve(response);
            },
            error: (response) => {
                reject(response);
            }
        })
    })
}

Sonra şöyle bir asyncfonksiyonda çağırın :

let response = await upload();

1
Kodunuz çalışmaz ... doğru yoldasınız ancak olduğu gibi çalışmaz.
ppetree

Lütfen daha fazla ayrıntı verebilir misiniz? Kodu test ettikten sonra bu soruyu cevapladım, işe yaramalı.
Taohidul İslam

await, zaman uyumsuz işlev dışında kullanılamaz, bir hata atar.
ppetree

Evet, cevabımın ikinci satırında bahsetmiştim, "Öyleyse bir asyncfonksiyonda çağır ".
Taohidul Islam

Bu harika bir çözüm ama (benim gibi) harika bir çözüm arayan diğerlerine yardımcı olmak için kodunuzu düzenlemeli ve daha eksiksiz bir şekilde göstermelisiniz. Belki de bir kemanla bağlantı içerir. Bu harika olurdu!
ppetree

0

Burada bahsedilen görmüyorum çünkü ben de jQuery ne zaman ifade bu amaç için çok yararlı olabilir işaret düşündüm .

Örnekleri şöyle:

$.when( $.ajax( "test.aspx" ) ).then(function( data, textStatus, jqXHR ) {
  alert( jqXHR.status ); // Alerts 200
});

"Then" bölümü, "when" bölümü bitinceye kadar yürütülmez.


0

İstek alınıncaya kadar beklemesi gerekir. Bundan sonra fonksiyon çağrıldığı yerden istek gövdesi getireceğim.

function foo() {
    var jqXHR = $.ajax({
        url: url,
        type: 'GET',
        async: false,
    });
    return JSON.parse(jqXHR.responseText);  
}

Lütfen çözümünüzü açıklayın.
Ayrılma

1
@Dropout eklendi.
Hassan Ejaz

Teşekkürler @Hassan Ejaz! Bir açıklaması olmayan ve sadece kod olan cevaplar düşük çaba olarak işaretlenir.
Ayrılma
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.