当我将阻塞函数放入队列时,为什么jQuery的动画会中断?

时间:2012-09-04 20:11:54

标签: jquery jquery-animate queue

当我第一次使用console.log(elem.queue());时,它会返回一个空数组[],但如果我将其更具体地称为console.log(elem.queue()[0]);,它会以正确的顺序为我提供单独的函数。在第一次之后,当我使用console.log(elem.queue());时,它返回正确的长度,但它以不同于它们应该的顺序返回函数,有时它返回undefined。但是当我使用console.log(elem.queue()[0]);时,它仍会返回预期的内容。这是我的代码以及输出的内容:

//The correct queue order is: animate, run, animate

console.log(elem.queue('jChain'));    //1: []
                                      //2+: [run(){}, animate(){}, undefined x 1]

console.log(elem.queue('jChain')[0]); //animate(){} 
console.log(elem.queue('jChain')[1]); //run(){}
console.log(elem.queue('jChain')[2]); //animate(){} 

如您所见,当我从队列中专门选择时,它是正确的。但是当我选择整个队列时,一切都会变得混乱。 有人可以告诉我发生了什么,为什么?

<小时/> 的更新
创建队列的代码:

console.log(queue); /* [{args:Array[2], method:"animate"},
                     *  {args:Array[2], method:"run"}, 
                     *  {args:Array[2], method:"animate"}] */
elem.clearQueue('jChain');
$.each(queue, function(key, value){
  if(value.method == 'animate'){
    value.args[1] = {duration:value.args[1], queue:'jChain' /*,complete:function(){elem.dequeue('jChain');}*/ };
    elem[value.method].apply(elem, value.args);
  }else{
    run.apply(elem, value.args);
  }
});

function run(fn, args){
  args = args || [];
  self = this;
  self.queue('jChain', function(next){
    if(fn)
        fn.apply(self, args);
    next();
  });
}

为什么这个奇怪的显示,我不知道。我正在尝试调试此代码,我认为这可能是什么阻碍了我。我不希望第二个动画执行,直到我的运行功能完成,它似乎应该工作,但它确实失败了。

Here is a jsFiddle of my code. - 确保在测试时打开控制台。如果控制台没有打开,它看起来会有效,所以打开它。注意“Subtitle”如何轻弹而不是淡入,并注意到队列顺序的差异。

2 个答案:

答案 0 :(得分:2)

我冒昧地尽可能多地展开,以了解发生了什么。

http://jsfiddle.net/kritzikratzi/YYwm9/1/

如果我理解正确,您会发生以下行为:

  1. 淡出
  2. 做一些console.log事情(或过程数据)
  3. 淡入
  4. 现在你可以尝试改变say-hello-loop的长度,对于我i < 5000次迭代,我可以看到动画的一半,i < 1我可以看到整个动画和{ {1}}动画消失了。 看起来jQuery似乎使用了创建新动画时绘制最后一帧的时间。 javascript是单线程的,你用你的for循环完全阻止浏览器,然后立即开始下一个动画,这会扰乱所有时间 - 动画在它开始之前结束。

    解决方案非常简单: 不要立即调用next(),但让jQuery的动画只需让浏览器快速重绘然后在下一帧开始动画就可以了。 长话短说:

    i < 10000

    在此测试:http://jsfiddle.net/kritzikratzi/YYwm9/2/

    好吧,我希望这是你要求的,有点不清楚你的实际问题是什么:)


    原始问题:为什么console.log(队列)无法正确显示?

    好吧,如果你查看queue()的jQuery源代码,你可以看到以下内容:

      // instead of this ... 
      next(); 
      // do this...
      window.setTimeout( next, 1 ); 
    

    所以队列可能是一些奇怪的jQuery对象而不是直接的数组,不要指望它能正确打印。正如另一个答案所指出的,使用toString()修复它。

答案 1 :(得分:1)

这似乎是让代码隐式转换数组的产物。如果你改为在JavaScript数组上使用显式的toString()方法,我发现输出是正确的,没有空数组或未定义的条目。在jsFiddle中,将四个console.log行中的第一行更改为:

的console.log(elem.queue( 'jChain')的toString());

将数组显式转换为字符串似乎可以正确地恢复内容。