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

Hob*_*use 230 ajax jquery

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

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

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

如何将用户正常重定向到登录页面?

$(".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;
            }
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

cgp*_*cgp 339

如果您不希望$.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;
            }
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

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

  • **永远不要使用`async:false`.**浏览器的事件循环将在等待不可靠的网络I/O时挂起.总有一种更好的方式.在这种情况下,链接的目标可以验证用户会话和302到登录页面. (65认同)
  • 在我看来,传递好的做法并不是在判断,而是StackOverflow上一些最佳答案的标志. (10认同)
  • @Matthew真的吗?在将用户发送到其他页面或刷新之前,使用async发送ajax的替代方法是什么? (4认同)
  • 对于测试,`async:false`非常有用. (3认同)
  • 在大多数浏览器用例中,不建议使用值为“ false”的“ async”。在较新版本的浏览器中可能会引发异常。请参阅https://xhr.spec.whatwg.org/#sync-warning(适用于xhr`open`方法的`async`参数,这是使用jQuery的方法)。 (2认同)
  • 请注意,async:false不支持跨域和jsonp请求。 (2认同)
  • @Matthew在与我们的技术负责人讨论之后,我倾向于同意他的建议,即对您的陈述做些微修改。**几乎从不使用`async:false` **。在某些情况下,这样做总是有意义的。 (2认同)

Mil*_*ike 39

我不使用$.ajax,但$.post$.get功能,所以如果我需要等待响应,我用这个:

$.ajaxSetup({async: false});
$.get("...");
Run Code Online (Sandbox Code Playgroud)


idr*_*sid 30

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

async: false
Run Code Online (Sandbox Code Playgroud)


kof*_*fus 23

您可能需要考虑在操作挂起时阻止UI,而不是将async设置为false(这通常是错误的设计).

这可以通过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();
}
Run Code Online (Sandbox Code Playgroud)

有了这个你现在可以做:

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));
});
Run Code Online (Sandbox Code Playgroud)

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

jsfiddle

  • 一点也不.将async设置为false会使请求异步 - 即停止处理直到它返回,这通常是不好的做法,例如,不会处理任何事件,其他ajax请求,超时等.您还可以修改上面的代码,以便在ajax处理时阻止部分UI(即它将影响的部分) (4认同)

小智 11

我认为如果你编写你的success函数来加载适当的页面而不是返回true或更简单的事情会更容易false.

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

window.location="appropriate page";
Run Code Online (Sandbox Code Playgroud)

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


Fra*_*man 7

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

他们的例子如下所示:

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

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


Tao*_*lam 6

在现代 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);
            }
        })
    })
}
Run Code Online (Sandbox Code Playgroud)

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

let response = await upload();
Run Code Online (Sandbox Code Playgroud)


小智 5

由于异步 ajax 已被弃用,请尝试使用带有 Promise 的嵌套异步函数。可能存在语法错误。


async function fetch_my_data(_url, _dat) {

   async function promised_fetch(_url, _dat) {

      return new Promise((resolve, reject) => {
         $.ajax({
            url:  _url,
            data: _dat,
            type: 'POST',
            success: (response) => {
               resolve(JSON.parse(response));
            },
            error: (response) => {
               reject(response);
            }
         });
      });
   }

   var _data = await promised_fetch(_url, _dat);
   
   return _data;
}

var _my_data = fetch_my_data('server.php', 'get_my_data=1');

Run Code Online (Sandbox Code Playgroud)