简体   繁体   English

jQuery ajax beforeSend

[英]jQuery ajax beforeSend

I have a simple AJAX call that is executing a function on the beforeSend and on complete .我有一个简单的 AJAX 调用,它在beforeSendcomplete上执行一个函数。 They execute fine but the beforeSend is "seemingly" not executed until after the success.他们执行得很好,但beforeSend直到成功之后才“似乎”执行。

On the beforeSend there is a "Please wait" notification.beforeSend有一个“请稍候”通知。 If I put a break after the function in the beforeSend then it will show that notification and then hit the success.如果我在beforeSend的函数之后放置一个中断,那么它会显示该通知,然后成功。 Without the break point then it will sit there and think while waiting for the response and then my please wait notification will appear for a fraction of a second after the success is hit.如果没有断点,那么它会坐在那里思考,等待响应,然后我的请等待通知将在成功命中后的几分之一秒内出现。

The desired functionality is to have the notification appear as soon as the request is sent so it displays while it is waiting for the response.所需的功能是在发送请求后立即显示通知,以便在等待响应时显示。

        $.ajax({
            type : 'POST',
            url : url,
            async : false,
            data : postData,
            beforeSend : function (){
                $.blockUI({
                    fadeIn : 0,
                    fadeOut : 0,
                    showOverlay : false
                });
            },
            success : function (returnData) {
                //stuff
            },
            error : function (xhr, textStatus, errorThrown) {
                //other stuff
            },
            complete : function (){
                $.unblockUI();
            }
        });

Your problem is the async:false flag.您的问题是async:false标志。 Besides the fact that it is bad practice (and really only makes sense in a very limited number of cases), it actually messes with the order of execution of the rest of the code.除了这是不好的做法(实际上只在非常有限的情况下才有意义)这一事实之外,它实际上扰乱了其余代码的执行顺序。 Here is why:原因如下:

It seems that somewhere in the blockUI code they are setting a setTimeout .似乎在blockUI代码的某个地方,他们正在设置setTimeout As a result, the blockUI code waits a very short amount of time.因此, blockUI代码等待的时间非常短。 Since the next instruction in the queue is the ajax() call, the blockUI execution gets placed right behind that.由于队列中的下一条指令是ajax()调用, blockUI执行就放在它的后面。 And since you are using async:false , it has to wait until the complete ajax call is completed before it can be run.并且由于您使用的是async:false ,因此它必须等到完整的ajax调用完成后才能运行。

In detail, here is what happens:详细来说,这是发生了什么:

  • You call blockUI你调用blockUI
  • blockUI has a setTimeout and gets executed after the timeout is done (even if the timeout length is 0, the next line, ajax() will be run first) blockUI有一个 setTimeout 并在超时完成后执行(即使超时长度为 0,下一行ajax()也会先运行)
  • ajax() is called with async:false , which means JS stops everything until the request returns ajax()async:false调用,这意味着 JS 停止一切,直到请求返回
  • ajax() returns successfully and JS execution can continue ajax()返回成功,JS 可以继续执行
  • the setTimeout inside blockUI code is probably over, so it will be executed next blockUI代码里面的setTimeout大概已经结束了,接下来会执行
  • it looks like blockUI runs as part of success , but in reality, it has just been queued up because of a timeout看起来像blockUI作为success一部分运行,但实际上,它只是因为超时而排队

If you would NOT use async:false , the execution would go as followed:如果您不使用async:false ,则执行将如下所示:

  • You call blockUI你调用blockUI
  • blockUI has a setTimeout and gets executed after the timeout is done (even if the timeout length is 0, the next line, ajax() will be run first) blockUI有一个 setTimeout 并在超时完成后执行(即使超时长度为 0,下一行ajax()也会先运行)
  • ajax() is called and sends of a request to the server. ajax()被调用并向服务器发送请求。
  • while it is connecting to the server, normal JS execution continues当它连接到服务器时,继续正常的 JS 执行
  • the setTimeout inside blockUI code is probably over, so it will be executed next blockUI代码里面的setTimeout大概已经结束了,接下来会执行
  • the blockUI text shows up blockUI文本出现
  • unless there is more JS code somewhere, JS execution is done until the AJAX success and complete callbacks are executed除非某处有更多的 JS 代码,否则将执行 JS 直到 AJAX success并执行complete回调

Here are some jsFiddle examples to demonstrate the problem:以下是一些 jsFiddle 示例来演示该问题:

Example 1 : This is the situation you are experiencing.示例 1 :这就是您遇到的情况。 The blockUI text doesn't show until after the ajax call executes. blockUI文本直到ajax调用执行后才会显示。

Example 2 : This is the exact same situation as yours, but with an alert before the ajax call.示例 2 :这与您的情况完全相同,但在ajax调用之前有一个alert Because there is an alert , the timeout inside blockUI places the appearance of the blockUI text after the alert instead of after the ajax .因为有一个alertblockUI内的超时将blockUI文本的外观blockUI alert而不是ajax

Example 3 : This is how it is supposed to work without async:false示例 3 :这就是没有async:false它应该如何工作

This is most probably because of async : false .这很可能是因为async : false As your call is synchronous, after your call to the $.ajax() function begins, nothing happens until the response is received, and the next thing as far as your code goes will be the success handler由于您的调用是同步的,因此在开始调用$.ajax()函数后,在收到响应之前不会发生任何事情,并且就您的代码而言,接下来的事情将是success处理程序

To make it work, You can do something like this为了使它工作,你可以做这样的事情

$.blockUI({
        fadeIn : 0,
        fadeOut : 0,
        showOverlay : false
});
// and here goes your synchronous ajax call
$.ajax({
            type : 'POST',
            url : url,
            async : false,
            data : postData,
            success : function (returnData) {
                //stuff
            },
            error : function (xhr, textStatus, errorThrown) {
                //other stuff
            },
            complete : function (){
                $.unblockUI();
            }
     });
$.blockUI({
        fadeIn : 0,
        fadeOut : 0,
        showOverlay : false
});
setTimeout(function() {
     $.ajax({
            type : 'POST',
            url : url,
            async : false,
            data : postData,
            success : function (returnData) {
                //stuff
            },
            error : function (xhr, textStatus, errorThrown) {
                //other stuff
            }
     });
},100);
$.unblockUI();

http://bugs.jquery.com/ticket/7464 http://bugs.jquery.com/ticket/7464

Another approach could be overload $.ajax function另一种方法可能是重载 $.ajax 函数

$.orig_ajax = $.ajax;

$.ajax = function() {
    var settings = {async: true};
    if (2 == arguments.length && 'string' == typeof arguments[0] && 'object' == typeof arguments[1])
        settings = arguments[1];
    else if (arguments.length && 'object' == typeof arguments[0])
        settings = arguments[0];

    if (!settings.async && 'function' == typeof settings.beforeSend) {
        var args = arguments;

        settings.beforeSend();
        var dfd = $.Deferred();
        setTimeout(function() {
            $.orig_ajax.apply($, args).then(dfd.resolve)
                                      .fail(dfd.reject);
        } ,100);
        return dfd.promise();
    } else
        return $.orig_ajax.apply($, arguments);
};

not perfect (because of different deferred object), but may be helpful..不完美(因为不同的延迟对象),但可能会有所帮助..

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM