jquery ajax beforesend

时间:2013-04-16 20:24:06

标签: javascript jquery jquery-blockui

我有一个简单的ajax调用,它在beforeSend和on complete上执行一个函数。它们执行得很好但是beforeSend“看似”在成功之后才会被执行。在发送之前有一个“请稍候”通知。如果我在beforeSend中的函数之后放了一个休息,那么它将显示该通知然后点击成功。没有断点,那么它将坐在那里等待响应时思考,然后我的请等待通知将在成功命中后出现几分之一秒。所需的功能是在请求发送后立即显示通知,以便在等待响应时显示。

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

4 个答案:

答案 0 :(得分:26)

您的问题是async:false标志。除了它是不好的做法(实际上只在非常有限的情况下才有意义),它实际上与其余代码的执行顺序混淆。原因如下:

似乎blockUI代码中的某个位置设置了setTimeout。结果,blockUI代码等待的时间非常短。由于队列中的下一条指令是ajax()调用,因此blockUI执行位于其后面。由于您使用的是async:false,因此必须等到完成ajax调用完成才能运行。

详细说明,会发生以下情况:

  • 您致电blockUI
  • blockUI有一个setTimeout并在超时完成后执行(即使超时长度为0,下一行,ajax()将首先运行)
  • 使用ajax()调用
  • async:false,这意味着JS会停止所有内容,直到请求返回
  • ajax()成功返回,JS执行可以继续
  • blockUI代码中的setTimeout可能已经结束,因此将在下一步执行
  • 看起来blockUI作为success的一部分运行,但实际上,由于超时,它刚排队等候

如果您不使用async:false,执行将如下:

  • 您致电blockUI
  • blockUI有一个setTimeout并在超时完成后执行(即使超时长度为0,下一行,ajax()将首先运行)
  • ajax()被调用并向服务器发送请求。
  • 当它连接到服务器时,正常的JS执行继续
  • blockUI代码中的setTimeout可能已经结束,因此将在下一步执行
  • 显示blockUI文字
  • 除非在某处有更多JS代码,否则执行JS执行直到执行AJAX successcomplete回调

以下是一些证明问题的jsFiddle示例:

Example 1:这是您遇到的情况。在blockUI调用执行后,ajax文本才会显示。

Example 2:这与您的情况完全相同,但在alert电话前有ajax。由于存在alertblockUI内的超时会将blockUI文字的外观置于alert之后,而不是ajax之后。

Example 3:这就是没有async:false

的情况

答案 1 :(得分:6)

这很可能是因为async : false。由于您的通话是同步的, 在您调用$.ajax()函数开始之后,在收到响应之前没有任何反应,而代码的下一步就是success处理程序

为了使它成功,你可以做这样的事情

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

答案 2 :(得分:0)

$.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

答案 3 :(得分:0)

另一种方法可能是重载$ .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);
};

不完美(因为延迟对象不同),但可能会有所帮助..