跳到主要内容

认识

一、什么是异步编程?


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');

2.3 Promise

2.4 Generator

2.5 Async/Await