如何让 jQuery 在返回之前等待 Ajax 调用完成?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/755885/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 09:44:25  来源:igfitidea点击:

How do I make jQuery wait for an Ajax call to finish before it returns?

jqueryajax

提问by Hobhouse

I have a server side function that requires login. If the user is logged in the function will return 1 on success. If not, the function will return the login-page.

我有一个需要登录的服务器端功能。如果用户登录,该函数将在成功时返回 1。如果没有,该函数将返回登录页面。

I want to call the function using Ajax and jQuery. What I do is submit the request with an ordinary link, with a click-function applied on it. If the user is not logged in or the function fails, I want the Ajax-call to return true, so that the href triggers.

我想使用 Ajax 和 jQuery 调用该函数。我所做的是使用普通链接提交请求,并在其上应用点击功能。如果用户未登录或函数失败,我希望 Ajax 调用返回 true,以便触发 href。

However, when I use the following code, the function exits before the Ajax call is done.

但是,当我使用以下代码时,该函数会在 Ajax 调用完成之前退出。

How can I redirect the user gracefully to the loginpage?

如何优雅地将用户重定向到登录页面?

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

回答by cgp

If you don't want the $.ajax()function to return immediately, set the asyncoption to false:

如果您不希望$.ajax()函数立即返回,请将async选项设置为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;
            }
        }
    });
});

But, I would note that this would be counter to the point of AJAX. Also, you should be handling the response in the errorand successfunctions. Those functions will only be called when the response is received from the server.

但是,我会注意到这与 AJAX 的观点背道而驰。此外,您应该处理errorsuccess函数中的响应。只有在从服务器收到响应时才会调用这些函数。

回答by MilMike

I am not using $.ajaxbut the $.postand $.getfunctions, so if I need to wait for the response, I use this:

我使用$.ajax的不是$.post$.get函数,所以如果我需要等待响应,我使用这个:

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

回答by idrosid

The underlying XMLHttpRequest object (used by jQuery to make the request) supports the asynchronous property. Set it to false. Like

底层 XMLHttpRequest 对象(由 jQuery 用于发出请求)支持异步属性。将其设置为false。喜欢

async: false

回答by kofifus

Instead of setting async to false which is usually bad design, you may want to consider blocking the UI while the operation is pending.

与其将 async 设置为 false(这通常是糟糕的设计),您可能需要考虑在操作挂起时阻止 UI。

This can be nicely achieved with jQuery promises as follows:

这可以通过 jQuery 承诺很好地实现,如下所示:

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

with this you can now do:

有了这个,你现在可以做:

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

And the UI will block until the ajax command returns

并且 UI 将阻塞,直到 ajax 命令返回

see jsfiddle

jsfiddle

回答by samuelagm

I think things would be easier if you code your successfunction to load the appropriate page instead of returning trueor false.

我认为如果您编写success函数以加载适当的页面而不是返回truefalse.

For example instead of returning trueyou could do:

例如,true您可以执行以下操作而不是返回:

window.location="appropriate page";

That way when the success function is called the page gets redirected.

这样,当调用成功函数时,页面会被重定向。

回答by Taohidul Islam

In modern JS you can simply use async/await, like:

在现代 JS 中,您可以简单地使用async/ await,例如:

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

Then call it in an asyncfunction like:

然后在一个async函数中调用它,如:

let response = await upload();

回答by Frank Hoffman

Since I don't see it mentioned here I thought I'd also point out that the jQuery whenstatement can be very useful for this purpose.

因为我没有看到这里提到它,所以我想我还要指出 jQuery when语句对于这个目的非常有用。

Their example looks like this:

他们的例子是这样的:

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

The "then" part won't execute until the "when" part finishes.

“then”部分在“when”部分完成之前不会执行。