认识
一、什么是异步编程?
JavaScript 语言 的执行环境是单线程
.所谓单线程
,就是指依次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,在执行后面一个任务,依次类推。
JavaScript 单线程:
- 优点: 实现起来比较简单,执行环境相对单纯
- 缺点: 只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。
JavaScript 单线程解决方案: 为了解决JavaScript 单线程带来的阻塞问题,JavaScript 语言将任务的执行模式分为两种:同步
和异步
;
。
- 同步模式: 后一个任务必须等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的。
- 异步模式: 每一个任务有一个或多个回调函数,前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则不是等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。
异步模式 非常重要。在浏览器端,耗时很长的操作都应该异步执行,避免浏览器失去响应
二、异步编程解决方案
2.1 回调函数
回调函数介绍 是异步编程最基本的方法
回调函数特点:
- 优点: 回调函数简单,容易理解和部署
- 缺点: 不利于代码的阅读和维护,各个部分之间高度耦合,流程会很混乱,而且每个任务只能指定一个回调函数。
回调函数实现:
假设有两个函数 f1 和 f2 , 后者等待前者的执行结果(f1 是一个很耗时的任务)
function f1(callback){
console.log('我是 f1函数');
setTimeout(() => {
callback();
}, 2000);
}
function f2(){
console.log('我是 f2函数');
}
f1(f2);
2.2 发布/订阅
我们经常使用的addEventListener
事件监听就是一种发布/订阅模式
发布/订阅特点:
发布/订阅实现:
//事件中心
function PubSub(){
this.callbacks={};
}
//订阅
PubSub.prototype.subscribe=function(key,fun){
(this.callbacks[key]||(this.callbacks[key]=[])).push(fun);
}
//发布
PubSub.prototype.publish=function(key,...args){
for(let fun of this.callbacks[key]){
fun.call(this,...args);
}
}
//取消订阅
PubSub.prototype.unsubscribe=function(key,fun){
const list=this.callbacks[key];
if(!list) return false;
if(!fun){
//不传入指定取消的订阅方法,则清空所有 key 下的订阅
list&&(list=[])
}else{
const index=list.findIndex(item=>item===fun);
index&&index.splice(index,1);
}
}
//创建事件中心实例
const pubsub=new PubSub();
//订阅 up 中的一个事件
pubsub.subscribe('up',up=>{
console.log('up'+up);
});
//订阅 down 中的一个事件
pubsub.subscribe('down',down=>{
console.log('down'+down);
});
//订阅 left 中的一个事件
pubsub.subscribe('left',left=>{
console.log('left'+left);
});
pubsub.publish('up','上上上');
pubsub.publish('down','下下下');
pubsub.publish('left','左左左');
pubsub.unsubscribe('right');