jQuery ajax,等待 beforeSend 动画完成

4

HTML和CSS:

<a href="#">link</a>
<img src="http://2.bp.blogspot.com/_OIHTbzY7a8I/TOaiTKLqszI/AAAAAAAAAHM/eb3iiOqxzKg/s640/Auto_Audi_Audi_concept_car_005130_.jpg" />
<div></div>

img { display: none; }
a { display: block; }

JS:

$("a").click(function(){
    $.ajax({
        url: "test.php",
        contentType: "html",
        beforeSend: function(){
            $("img").fadeIn(600, function(){
                $("div").append(" | beforeSend finished | ");
            });
        },
        error: function(){
            $("div").append(" | error | ");
        }
    });
    return false
});

问题是,在beforeSend函数中的动画完成之前,error函数就开始了。
这里有一个可行的例子:http://jsfiddle.net/H4Jtk/2/ error应该在beforeSend完成后才开始工作。如何做到呢?
我使用beforeSend函数在ajax开始时启动块的动画。我不能删除它。
谢谢。
3个回答

10
您可以使用自定义事件来等待动画完成,如下所示:
$("a").click(function(){
    var img = $("img"),
        div = $("div");
    $.ajax({
        url: "test.php",
        contentType: "html",
        beforeSend: function(){
            img.fadeIn(600, function(){
                div.append(" | beforeSend finished | ");
                div.trigger("animationComplete");
            });
        },
        error: function(){
            if(img.is(':animated')) {
                div.one("animationComplete", function() {
                    div.append(" | error | ");
                });
            } else {
                div.append(" | error | ");
            }
        }
    });
    return false
});

注:

  1. jQuery.one()添加一个事件处理程序,它会触发一次然后被删除。
  2. jQuery.is(':animated')是由jQuery提供的自定义选择器,用于确定元素是否使用jQuery内置的动画方法(例如fadeIn)进行了动画处理。

新jsFiddle:http://jsfiddle.net/pgjHx/


在评论中,Happy问如何处理多个动画。一种方法是向animationComplete事件处理程序添加条件,以查看动画是否正在进行。例如:

$("a").click(function(){
    var img = $("img"),
        div = $("div");

    $.ajax({
        url: "test.php",
        contentType: "html",
        beforeSend: function(){
            img.fadeIn(600, function(){
                div.append(" | beforeSend finished | ");
                div.trigger("animationComplete");
            });

            // Add another animation just to demonstrate waiting for more than one animation
            img.animate({
                marginTop: '-=5',
                opacity: '-=.5'
            }, 700, function() {    
                div.trigger("animationComplete");
            });
        },
        error: function(){
            if(img.is(":animated")) {
                // Note I've switched to bind, because it shouldn't be unbound
                // until all animations complete
                div.bind("animationComplete", function() {
                    if(img.is(":animated")) {
                        return;
                    }
                    div.append(" | error | ");
                    div.unbind("animationComplete");
                });
            } else {
                div.append(" | error | ");
            }
        }
    });
    return false
});

我想在不使用is(:animated)的情况下使用它 http://jsfiddle.net/H4Jtk/4/ 运行良好。 - James
1
@Happy,你可以将事件排队(请参见http://api.jquery.com/animate/上的队列选项),然后在最后一个动画中触发“animationComplete”事件,或者你可以维护某种活动动画计数器(例如,在单击事件处理程序的顶部添加`var animationCount = 0,然后在每个调用动画之前添加animationCount++,然后在animationComplete处理程序的开头添加animationCount--; if(animationCount > 0) return`)。 - eyelidlessness
@Praveen,我正在创建一个自定义事件处理程序和自定义事件名称;DOM或jQuery中没有本地的animationComplete事件,我只是选择了这个描述性名称。 - eyelidlessness
@eyelidlessness 你是个超级巨星! - James
@Happy,我重新考虑了一下我对于多个动画的评论,我认为我让事情变得比必要的还要复杂。我会编辑我的回答,以提供更简单解决方案的细节。 - eyelidlessness
显示剩余5条评论

1

你可以做到这个

//在链接点击时运行您的动画,当动画完成后, //再开始您的ajax请求。

$("a").click(function () {
    $("img").fadeIn(600, function () {
        $("div").append(" | beforeSend finished | ");
         $.ajax({
                    url: "test.php",
                    contentType: "html",
                    error: function () {
                        $("div").append(" | error | ");
                    }
                });
                return false
            });
    });
});

这个解决方案将XHR请求延迟了600毫秒,这是一个明显的延迟。我可以理解为什么Happy不想这样做。 - eyelidlessness

-1
问题在于 "beforeSend" 已经完成 - 它会在 "fadeIn" 完成之前退出。我不知道你想要实现什么,所以很难提供解决方案。如果你想要保证这个操作先发生,你必须等待动画序列(即 "fadeIn")完成后才开始 ajax 操作。

我使用beforeSend函数在ajax开始时启动块的动画。当动画完成后,我通过反向动画在成功时显示数据上的错误消息。现在更清楚了吗? - James
Happy 正在尝试完成以下任务:1. XHR 调用立即触发;2. beforeSend 处理程序负责处理 XHR 请求开始时发生的操作;3. error 事件等待 beforeSend 操作完成后再进行 DOM 更改,以避免顺序混乱。这可以通过自定义事件实现,而不会延迟 XHR 请求。 - eyelidlessness

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接