在while循环锁定浏览器时暂停执行(用fiddles更新)

时间:2013-12-12 14:02:45

标签: javascript jquery

我知道我的问题我不知道如何解决它。我有一个自定义域,并在函数调用中执行while循环。在那个循环中,我希望按顺序发生动画。

所以第一个问题是javascript本质上执行每一行,因此第2项在第1项完成之前开始。现在效果是如此之短,以至于它“出现”同时发生在所有元素上,但在调试器中它只是一次循环一个。

现在我的典型解决方案是使用SetTimeout(),但这会导致浏览器锁定。阅读这篇文章(Trying to delay/pause/slow a while loop in jQuery),浏览器进入无限循环是有道理的。

那么如何在element1和element2事件之间获得暂停?我想也许可以在我的自定义域中添加一个回调函数,但不确定它是否能按预期工作,除了不确定如何操作。

在页面的头部,阅读评论中的其他任何我可能做错了或可以做得更好。

$(document).ready(function ()
{
    //pause long enough for person to visually take in page before starting
    setTimeout(function () { PageLoadAnimation.onReady(); }, 1000);
});

我的自定义域名:

var PageLoadAnimation = 
{
    onReady: function ()
    {
        //black everything out just to be sure
        PageLoadAnimation.BlackOutElements();

        //flash & show
        PageLoadAnimation.FlashElement();

    },

    BlackOutElements: function ()
    {
        $('#ParentContainer').children().hide();
    },

    FlashElement: function ()
    {
        //get array of all elements and loop till all are visible
        var elementArray = $('#ParentContainer').children();

        var $els = $('#PartialsContainer').children();

        while (elementArray.length)
        {
           var $el = elementArray.eq(Math.floor(Math.random() * elementArray.length));

           //if I put set timeout here is causes the infinite loop
           PageLoadAnimation.FlashBlast($el);

           elementArray = elementArray.not($el);

           //if I put by itself it no diff as the while loop continues regardless
           //setTimeout(1500);


        }
    },

    FlashBlast: function ($el)
    {
       //flash background
       $el.fadeIn(200, function () { $el.fadeOut(200) });
    }

}

我不确定它是否无效或我做错了所以我创造了这些小提琴:

Original Fiddle

With Johan Callbacks

Using is animating property 警告这一个会挂你的浏览器! 我不认为我按照约翰的方式检查isAnimating属性吗?


对此情况的回答。希望它能帮助别人。

循环中的

setTimeout确实是我的问题......但不是唯一的问题。我是另一个问题。

我先。

我是傻瓜我真的因为我做错了两件事而引起了我自己的并发症。

首先使用jsfiddle我的javascript会因为语法或某些这样的事情而错误但是小提琴并没有告诉你(据我所知)所以我的小提琴不会运行但是我自豪地把它当作我的代码很精细愚蠢的javascript没有用。

第二,我错误地将我的函数传递给setTimeout。我正在添加函数parens(),这也不正确,这会让我回到上面的问题。

WRONG: intervalTimer = setInterval(MyFunction(), 1500);

RIGHT: intervalTimer = setInterval(MyFunction, 1500);

至于我在这里读到的代码(http://javascript.info/tutorial/settimeout-setinterval)在循环中设置超时是不好的。循环将快速迭代,并且超时循环中的一个步骤我们进入一个循环的射击小队。

这是我的实施:

我创建了几个变量,但不希望它们污染全局范围,所以我在自定义域中创建了它们。一个用于保存元素数组,另一个用于setInterval对象的句柄。

var PageLoadAnimation =
               {
                   elementArray: null,
                   intervalTimer: null,
                   ....
                }

在我的onReady函数中(页面调用该函数)我设置了我的域数组变量并设置了保存句柄的间隔以供以后使用。请注意,间隔计时器是图像闪烁之间所需的时间。

onReady: function () 
      {
         elementArray = $('#PartialsContainer').children();

         //black everything out just to be sure
         PageLoadAnimation.BlackOutElements();

         //flash & show
         intervalTimer = setInterval(PageLoadAnimation.FlashElement, 1500);

       },

现在不是循环遍历数组,而是以一定的间隔执行一个函数,只跟踪要闪存的数组中剩余的元素数量。一旦数组中有零个元素,我就会终止执行间隔。

FlashElement: function () 
{

   if(elementArray.length > 0) //check how many elements left to be flashed
   {
      var $el = PageLoadAnimation.GrabElement(); //get random element
      PageLoadAnimation.FlashBlast($el); //flash it
      PageLoadAnimation.RemoveElement($el); //remove that element
   }
   else
   {
      //done clear timer
      clearInterval(intervalTimer);
      intervalTimer = null;
   }


},

所以整个事情是:

var PageLoadAnimation =
               {
                   elementArray: null,
                   intervalTimer: null,

                   onReady: function () {
                       elementArray = $('#PartialsContainer').children();

                       //black everything out just to be sure
                       PageLoadAnimation.BlackOutElements();

                       //flash & show
                       intervalTimer = setInterval(PageLoadAnimation.FlashElement, 1500);
                       //NOT this PageLoadAnimation.FlashElement()

                   },

                   BlackOutElements: function () {
                       $('#PartialsContainer').children().hide();
                   },

                   FlashElement: function () 
                   {

                       if(elementArray.length > 0)
                       {
                           var $el = PageLoadAnimation.GrabElement();
                           PageLoadAnimation.FlashBlast($el);
                           PageLoadAnimation.RemoveElement($el);
                       }
                       else
                       {
                           //done clear timer
                           clearInterval(intervalTimer);
                           intervalTimer = null;
                       }


                   },

                   GrabElement: function()
                   {
                       return elementArray.eq(Math.floor(Math.random() * elementArray.length));
                   },

                   RemoveElement: function($el)
                   { elementArray = elementArray.not($el); },

                   FlashBlast: function ($el) {
                       //flash background
                      $el.fadeIn(100, function () { $el.fadeOut(100) });
                   }



               }

希望帮助其他人了解在javascript中暂停执行的方法。

1 个答案:

答案 0 :(得分:1)

可能有帮助的回调示例:

FlashBlast: function ($el, fadeInComplete, fadeOutComplete)
{
   if(arguments.length === 3){

       $el.fadeIn(200, function () {
           fadeInComplete();
           $el.fadeOut(200, fadeOutComplete);
       });
   }

}

用法:

PageLoadAnimation.FlashBlast($el, function(){
    //fadein complete
}, function(){
    //fadeout complete
});

另一个可能有用的想法:

 isAnimating: false,

 FlashBlast: function ($el)
 {
     var dfd = $.Deferred(),
         that = this;

     that.isAnimating = true;

     $el.fadeIn(200, function () { 
         $el.fadeOut(200, function(){
             dfd.resolve();
         }) 
     });

     dfd.done(function(){
         that.isAnimating = false;
     });
 }

然后使用私有财产isAnimating

最后,要知道元素是否在动画下,您可以使用$el.is(':animated')

希望这会有所帮助。如果有什么不清楚,请告诉我。