Javascript语言的执行环境是"单线程"(single thread)
,Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。
"同步模式"就是上一段的模式,后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的;"异步模式"则完全不同,每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。
异步的4中方法
1、回调函数
// 这是两个函数
f1();
f2();
// 改写f1
function f1(callback){
setTimeout(function () {
// f1的任务代码
callback();
}, 1000);
}
f1(f2);
f1不会堵塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作推迟执行。
优点:简单、容易理解和部署;
缺点:不利于代码的阅读和维护,各个部分之间高度耦合(Coupling),流程会很混乱,而且每个任务只能指定一个回调函数。
2、事件监听
采用事件驱动模式。任务的执行不取决于代码的顺序,而取决于某个事件是否发生。
f1.on('done', f2);
function f1(){
setTimeout(function () {
// f1的任务代码
f1.trigger('done'); //执行完成后,立即触发done事件,从而开始执行f2
}, 1000);
}
优点:比较容易理解,可以绑定多个事件,每个事件可以指定多个回调函数,而且可以"去耦合"(Decoupling),有利于实现模块化;
缺点:整个程序都要变成事件驱动型,运行流程会变得很不清晰。
3、发布 / 订阅(观察者模式)
将上一节的事件理解成“信号”
存在一个"信号中心",某个任务执行完成,就向信号中心"发布"(publish)一个信号,其他任务可以向信号中心"订阅"(subscribe)这个信号,从而知道什么时候自己可以开始执行。
jQuery.subscribe("done", f2); //f2向"信号中心"jQuery订阅"done"信号。
function f1(){
setTimeout(function () {
// f1的任务代码
jQuery.publish("done"); //f1执行完成后,向"信号中心"jQuery发布"done"信号,从而引发f2的执行
}, 1000);
}
jQuery.unsubscribe("done", f2); //f2完成执行后,也可以取消订阅(unsubscribe)。
优点:可以通过查看"消息中心",了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行。
4、Promise
每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。
优点:回调函数变成了链式写法,程序的流程可以看得很清楚;如果一个任务已经完成,再添加回调函数,该回调函数会立即执行。所以,你不用担心是否错过了某个事件或信号。
缺点:难理解?