“异步模式”:每一个任务有一个或多个回调函数,前一个任务结束后,不是执行下一个任务,而是执行这个回调函数。后一个任务不等前一个任务结束就执行。
异步编程的四种方法:1.回调函数2.事件监听3.发布- 订阅者模式4.Promise对象
一、回调函数
假定有两个函数f1和f2,后者等待前者的执行结果
f1();
f2();
如果f1是一个非常耗线程的任务,考虑改写f1,把f2写成f1的回调函数
function f1(callback) {
setTimeout({
function () {
//执行f1的代码
callback();
}
},3000)
}
f1(f2);
优点:简单,容易理解。缺点:各个部分之间高度耦合,流程复杂,每一个任务只能指定一个回调函数
二、事件监听
另一个思路就是采用事件驱动模式。任务的执行不取决代码的顺序,而是取决于某个事件是否发生。
首先:给f1绑定事件
f1.on("done",f2)
然后:改写f1函数
function f1() {
setTimeout(function () {
//执行f1的代码
f1.trigger("done")
},3000)
}
优点:可以绑定多个事件,每个事件可绑定多个回调函数,可以去耦合,有利于模块化。缺点:整个程序都要变成事件驱动型,运行流程会变的非常不清晰。
三、发布/订阅者模式
我们假定存在一个“信号中心”,某个任务执行完成后就向“信号中心”发布一个信号,其它任务可以向“信号中心”订阅这个“信号”,从而知道自己什么时候开始执行。
首先,f2向“信号中心”JQuery订阅“done”信号
jquery.subscribe("done",f2)
然后,改写f1
function f1 () {
setTimeout(function () {
//执行f1的代码
jquery.publish("done")
},3000)
}
我们可以通过查看“消息中心”,了解存在有多少个信号,每个信号有多少个订阅者,从而监控程序的运行。
四、Promise对象
简单说,它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。比如,f1的回调函数f2,可以写成:
f1().then(f2);
f1要进行如下改写(这里使用的是jQuery的实现):
function f1(){
var dfd = $.Deferred();
setTimeout(function () {
// f1的任务代码
dfd.resolve();
}, 500);
return dfd.promise;
}
这样写的优点在于,回调函数变成了链式写法,程序的流程可以看得很清楚,而且有一整套的配套方法,可以实现许多强大的功能。
比如,指定多个回调函数:
f1().then(f2).then(f3);
再比如,指定发生错误时的回调函数:
f1().then(f2).fail(f3);
而且,它还有一个前面三种方法都没有的好处:如果一个任务已经完成,再添加回调函数,该回调函数会立即执行。所以,你不用担心是否错过了某个事件或信号。这种方法的缺点就是编写和理解,都相对比较难。
详细讲解见:http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html