我怎样才能运行很多个函数依次执行?

How can I run a lot of functions in sequence?

也许这个问题是重复的。我发现了很多类似的问题,但没有人能真正解决我的问题。这是我的任务:

function animate(){
  $ul.each(function(){
     $(this).find('li').each(function(){
          //animate block
          $(this).animate({top:'-100%'},100,function(){
             $(this).css({top:'100%'});
          });
          //endblock
        });
     });
}

如您所知,'animate block' 个函数将同时 运行。我希望它们按顺序 运行。我怎样才能做到这一点?

我已经阅读了 jQuery 'deferred'、'Q' 相关文章,但仍然感到困惑。

对不起我的英语。

---------加法-----

如果我想运行动画函数多次,我应该怎么做?

像这样的东西应该可以工作:

var last_deferred = $.Deferred();
last_deferred.resolve();

$ul.each(function(){
    $(this).find('li').each(function(){
         var deferred = $.Deferred(),
             $that = $(this);
         last_deferred.then(function() {
             $that.animate({top:'-100%'},100,function(){
                $(this).css({top:'100%'});
                deferred.resolve();
             });
         });
         last_deferred = deferred;
    });
});

说明:这里我使用了延迟对象的两个重要特性.then.resolve。当您调用 .resolve(); 时,延迟对象将触发通过 .then 分配给它的所有处理程序。所以发生的事情是我首先定义 "dummy" deferred 我立即解决。如果延迟对象已解析,则通过 .then 添加处理程序将自动使其成为 运行。那么会发生什么

  1. last_deferred已定义并解决
  2. 临时 deferred 已创建
  3. .then 处理程序添加到 last_deferred
  4. .then 处理程序被触发,并在它完成一些事情后解析 deferred(因此在 deferred 上触发 .then
  5. last_deferred 重新定义为 deferred
  6. 回到2.

所以这是一种异步循环(因为 .animate 是一个异步操作)。在每一步你说 "when previous deferred is resolved tell it to resolve the next one".

使用 queue() 函数检查此解决方案。

此函数等待动画完成,然后执行它的内容。

var anim = function(i) {
  $('.test').eq(i).animate({'top':'20px'}, 350).queue(function() {
    i++;
    anim(i);
    $(this).dequeue();
  });
}
anim(0);
.test {
  width:50px;
  height:50px;
  float: left;
  margin-right:10px;
  background-color:green;
  position:relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="test">test</div>
<div class="test">test</div>
<div class="test">test</div>
<div class="test">test</div>
<div class="test">test</div>
   

如果你想避免 jQuery 的尴尬 .queue()/.dequeue(),那么你可以从 [=16] 的 jQuery 集合构建一个承诺链=] 元素。

function animate($ul) {
    var p = $.when(); //resolved starter promise
    $("li", $ul).each(function(i, li) {
        p = p.then(function() {
            return $(li).animate({ top:'-100%' }, 100, function() {
                return $(li).css({ top:'100%' });
            }).promise();
        });
    });
    return p;
}

随着链条的固定,动画将按顺序出现。

更优雅的是,您可以扩展 jQuery 以拥有一个 .reduce() 方法,从 Array.prototype 中采用。

jQuery.fn.reduce = Array.prototype.reduce;

然后,通过在 jQuery 集合上调用 .reduce() 来构建所需的承诺链。

function animate($ul) {
    return $("li", $ul).reduce(function(p, li) {//wow, jQuery has a .reduce() method!
        return p.then(function() {
            //Here, perform the required animation and return a promise of its completion.
            return $(li).animate({top:'-100%'}, 100, function() {
                $(li).css({top:'100%'});
            }).promise();
        });
    }, $.when());//Resolved starter promise, ie p in the first iteration of .reduce() .
}

这个模式非常值得学习,因为它有很多应用。

在这两个示例中,最外层的 return 允许您在调用 animate() 的任何地方链接 .then() :

animate($("ul")).then(function() {
    //do something when all the <li> animations have completed.
});

尝试利用 .queue() , $.map() , .delay() ;将 window.innerHeight 替换为 100 ,将 px 单元替换为 .animate() 处的 % 单元;在 complete 回调

处用 .animate 替换 .css

var ul = $("ul");
ul.queue("_fx", $.map(ul.find("li"), function(el, i) {
  return function(next) {
    return $(el).animate({
      top: "-" + window.innerHeight / 10 + "px"
    }, 100, function() {       
      $(this).delay(100).animate({
        top: window.innerHeight - $(this).height() * 1.5 + "px"
      }, 100, next);
    })
  };
})).dequeue("_fx");
body {
  height: 200px;
}
ul li {
  top: 150px;
  position: relative;
  width: 50px;
  height: 50px;
  background: red;
  padding 8px;
  display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<ul>
  <li>a
  </li>
  <li>b
  </li>
  <li>c
  </li>
  <li>d
  </li>
  <li>e
  </li>
  <li>f
  </li>
  <li>g
  </li>
</ul>