用同步的方式执行jQuery异步动画

在编写jQuery动画时,通过回调函数进行动画队列的编排,但当回调过多,往往会出现这样的代码:

1 $(".box1").fadeIn(1000,function(){
2    $(".box2").fadeIn(1000,function(){
3       $(".box3").hide(1000,function(){
4           // todo xxx
5        })
6     })
7 })

那么是否可以将这种层次的回调以链式的写法完成呢?

如:f(fn1).f(fn2).f(fn3)... 表示fn1执行完成后fn2,fn2执行完成后执行fn3,...

下面逐步介绍实现方式:

1、确定结构:

为实现链式调用,需要f()的返回值一个包含其本身的对象

function f(n){
   var obj = {};
   obj.f = f;
   return obj;
}

这样就构造好了链式调用的基本结构。

尝试加入参数:

function f(n){
   console.log(n);
   var obj = {};
   obj.f = function(m){return f(m);};
   return obj;
}

与我们预想的结果相同,但如结果所见,f调用()会立即将参数代入执行。现在增加一个需求,希望f().f().f()...仅表示一个序列,真正的执行需要我下达其他命令后才发生。于是我们需要在f()的obj中加入一个函数run(),此函数用来下达执行指令,修改代码如下:

1 function f(n){
2    var obj = {};
3    obj.f = function(m){return f(m);};
4    obj.run = function(){
5        console.log(n)
6    }
7    return obj;
8 }

可以看到,在我们原先的代码并没有输出结果,而当我们执行run()后会怎样呢?

可以看到仅输出了第三次结果,这是因为run()并没有保存前两次f()参数的值,我们期望的将三次f()一并执行,实际上仅仅执行了第三次。那么如何解决这个问题呢,换句话说:如何在run()中保存所有之前获得的f()的参数呢?

2、保存参数:

    我们知道,函数通过参数获得函数外部变量的值,这里我们就通过这种方式保存f()的所有参数,代码修改如下:

 1 function f(n,fn){
 2     var obj = {};
 3     obj.arr = fn===undefined?[]:[fn];
 4     obj.arr.push(n);
 5     obj.f = function(m){return f(m,n);};
 6     obj.run = function(){
 7         $.each(obj.arr,function(i,fn){
 8             fn();
 9          });
10     }
11     return obj;
12  }

f()中添加obj.arr数组,用来保存所有传入的参数,而run()统一执行所有传入的参数,f()的第二个参数为上一次传入的参数,这样上一次执行所需的参数就被保存了下来。我们将传入的参数换成函数,用如下代码测试:

可以看到这正是我们想要的结果。

再次向后追加,希望输出1 2 3,但实际只输出后两次结果,原因在于f()的第二个参数仅保存了上一次传入的参数,而不是前几次的

f()的第二个参数为数组,用来保存前几次已传入的参数,修改代码如下:

function f(n,ar){
   var obj = {};
   obj.arr = ar===undefined?[]:ar;
   obj.arr.push(n);
   obj.f = function(m){return f(m,obj.arr);};
   obj.run = function(){
      $.each(obj.arr,function(i,fn){
         fn();
      });
  }
 return obj;
}

再次执行之前的代码,已符合预期。

3、执行回调

f(
    function () {
       $(".box1").fadeIn(1000);
    }
  ).f(
     function () {
        $(".box2").fadeIn(1000);
    }
 ).run();

执行上述代码,我们希望看到的是box1用1秒淡入,这个动画执行完后,box2开始执行1秒淡入,但实际上,这两个动画几乎是同时执行,所以接下来的关键是如何执行回调。修改测试代码如下:

f(
    function (cb1) {
       $(".box1").fadeIn(1000,cb1);
    }
  ).f(
     function (cb2) {
        $(".box2").fadeIn(1000,cb2);
    }
 ).run();

我们看到,cb1和cb2分别为box1和box2执行动画的回调函数,也就是说,我们希望达到这样的效果:在cb1中,执行box2的动画,在cb2中执行后面的动画(如果有),即:需要在cb中下达执行下一个f()中函数的指令。而run()仅仅是控制f()当前携带函数的执行,修改代码如下:

function f(n,ar){
   var obj = {};
   obj.arr = ar===undefined?[]:ar;
   obj.arr.push(n);
   obj.f = function(m){return f(m,obj.arr);};
   obj.run = function(){
     var fn = obj.arr.shift();
     if(typeof fn === "function") fn(callback);
   }
   function callback(){
      obj.run();
   }
   return obj;
}
f(
    function (cb) {
       $(".box1").fadeIn(1000,cb);
    }
  ).f(
     function (cb) {
        $(".box2").fadeIn(1000,cb);
    }
 ).run();

再次执行以上代码进行测试,实现box1执行完成后执行box2,目标实现

时间: 2024-08-24 07:27:46

用同步的方式执行jQuery异步动画的相关文章

jQuery使用数据绑定的方式来执行元素的动画【原】

网页排版中如果有大量的元素动画并且使用jquery的animate来生成,写出来的js代码又多又乱:换一种方式:把动画的属性绑定到动画元素上,再写一个通用的方法去读取这些属性然后自动的生成对应的动画:或许这样可以省点力气,看起来也更加直观. <!DOCTYPE html> <html> <head> <title>使用数据绑定的方式来执行元素的动画</title> <meta charset="utf-8"> &l

linux 异步信号的同步处理方式

关于代码的可重入性,设计开发人员一般只考虑到线程安全,异步信号处理函数的安全却往往被忽略.本文首先介绍如何编写安全的异步信号处理函数:然后举例说明在多线程应用中如何构建模型让异步信号在指定的线程中以同步的方式处理. 应用中编写安全的信号处理函数 在开发多线程应用时,开发人员一般都会考虑线程安全,会使用 pthread_mutex 去保护全局变量.如果应用中使用了信号,而且信号的产生不是因为程序运行出错,而是程序逻辑需要,譬如 SIGUSR1.SIGRTMIN 等,信号在被处理后应用程序还将正常运

同步执行与异步执行

计算机程序执行分为同步执行和异步执行 (1)同步执行 所谓的同步执行,就是正常的计算机程序执行的3大顺序流程: 顺序控制语句:从上至下,从左至右 分支控制语句:if,switch 循环控制语句:for(),while,do...while,for...in,forEach() (2)异步执行 所谓的异步执行,是一种特殊的程序的执行方式: setInterval(定时器),setTimeout(延时器) 事件的绑定 onclick,onopen,onscroll... ajax请求 (3)同步执行

如何防止jQuery对象动画重复执行

如何防止jQuery对象动画重复执行:很多朋友可能会遇到这样的时候,如果有一个mouseover事件触发的动画效果,如果鼠标连续移入的话,可能会导致动画被多次执行,这种情况很可能是我们不想要的下过,下面就介绍一下如何防止此种现象的发生.代码如下: if(!$(".content").is(":animated")){ //code } 上面的代码就是判断指定元素是否处于动画之中,如果没有处于动画之中,则执行响应操作.相关阅读:1.is()函数可以参阅jQuery的i

GCD网络多线程---同步执行,异步执行,串行队列,并行队列

总结:同步(不管是串行还是并行)----不开辟子线程 异步(不管是串行还是并行)----开辟子线程 GCD: dispatch queue 主线程的main queue 并行队列 global dispatch queue 串行队列serial queues 一般用于按顺序同步访问 #pragma mark - 加载多线程 - (void) _loadMutil { //GCD基于C语言 //1.主对列:(串行队列) dispatch_queue_t mainQueue=dispatch_get

jQuery异步获取json数据的2种方式

jQuery异步获取json数据有2种方式,一个是$.getJSON方法,一个是$.ajax方法.本篇体验使用这2种方式异步获取json数据,然后追加到页面. 在根目录下创建data.json文件: { "one" : "Hello", "two" : "World" } ■ 通过$.getJSON方法获取json数据 <script src="Scripts/jquery-2.1.1.min.js"

Jquery异步功能实例

Jquery确实是一个很好的JavaScript框架,今天利用闲暇时间给大家一个借助Jquery异步实现校验用户名的唯一性的例子: 代码1--index.jsp文件: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String basePath = request.getScheme()+&quo

GCD下的几种实现同步的方式

GCD多线程下,实现线程同步的方式有如下几种: 1.串行队列 2.并行队列 3.分组 4.信号量 实例: 去网上获取一张图片并展示在视图上. 实现这个需求,可以拆分成两个任务,一个是去网上获取图片,一个是展示在视图上. 这两个任务是有关联的,所以需要同步处理. 下面看这几种方式如何实现. 一. 1.串行队列 1.1[GCD相关:] (1)GCD下的dispatch_queue队列都是FIFO队列,都会按照提交到队列的顺序执行. 只是根据队列的性质,分为<1>串行队列:用户队列.主线程队列 &l

同步I/O操作和异步I/O操作

当执行I/O操作的时候,无论是同步I/O操作还是异步I/O操作,都会调用的Windows的API方法,比如,当读取文件的时候,调用ReadFile函数.该方法会将你的当前线程从用户态转变成内核态,会生成一个I/O请求包,并且初始化这个请求包,这个包中包含一个文件句柄,一个偏移量和一个Byte[]数组.ReadFile会向内核传递,根据这个请求包,windows内核知道需要将这个I/O操作发送给哪个硬件设备.这些I/O操作会进入设备自己的处理队列中,该队列由这个设备的驱动程序维护. 如果此时是同步