前置知识
JS语言的执行环境是"单线程", 也就是我们写的所有js代码都是在一个线程(主线程)上执行
理解单线程:
就是指一次只能完成一件任务。 如果有多个任务,就必须排队,前一个任务完成,再执行后面一个任务,以此类推
js执行任务的2种模式
同步(Synchronous)
- 后一个任务等待前一个任务结束,然后再执行,
- 程序的执行顺序与任务的排列顺序是一致的、同步的
异步(Asynchronous)
- 每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,
- 后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。
为什么需要异步JS?
浏览器端:
- 耗时很长的操作都应该异步执行,避免浏览器失去响应
- 给时机让浏览器能去更新界面, 响应用户操作
Node端:
- "异步模式"是唯一的模式,执行环境是单线程的
- 处理请求的回调函数/数据库操作/文件读写操作都必须是异步处理, 否则处理多个请求时很快就会失去响应
JS常用的异步编码方式
- 回调函数
- 事件机制
- 消息订阅与发布 / 全局事件总线
- Promise
- async & await
回调函数
1.异步编程最基本的方法,所有模式都是在此基础上进行封装而来
2.回调函数的执行方式:
(1)异步执行
(2)同步执行
3.异步回调的缺点:
(1)不利于代码的阅读和维护
(2)容易出现回调地狱的问题
事件机制
1.事件驱动模式:
(1)任务执行不取决于代码定义的顺序,而取决于某个事件是否发生
(2)事件监听函数定义时不会执行,只有当事件发生时才会执行
2.分类:
(1)原生DOM事件
(2)自定义事件
3.操作:
(1)在某个元素或者组件上绑定特有监听事件
(2)在某个元素或者组件上分发事件
消息订阅和发布与全局事件总线
- 消息订阅/发布:
订阅全局消息
发布全局消息
- 全局事件总线:
绑定事件监听
分发事件
- 特点: 分发事件后, 所有同名的事件监听回调都会调用
Promise
- 实现异步编程新的通用解决方案
- 相对于纯回调的优势
- 指定异步回调函数的方式更灵活(可以在启动异步任务后,甚至可以在任务完成后)
- 通过then的链式调用解决回调地狱的问题
- 不足: 还需要指定回调函数
async/await
- 基于promise的语法糖, 简化了promise对象的使用(不再使用回调函数编码)
- 以同步编码方式实现的异步流程
- 是js异步编程的终极解决方案(基本上可以这样说)
JS事件循环机制
- s是单线程运行的
- js的回调函数可以异步执行, 也可以同步执行
- js通过event-loop机制实现了js的单线程异步执行
- JS引擎解析执行js代码总是在主线程执行(WebWorks除外)
- 浏览器有在分线程执行的对应管理模块(浏览器是多线程执行的)
- 定时器
- DOM事件监听
- ajax请求
- Promise
- MutationObserver
- JS引擎有专门的回调队列, 缓存待执行的回调函数
- 宏队列
- 微队列
Promise深入理解
- 如何改变promise的状态?
- 一个promise指定多个成功/失败回调函数, 都会调用吗?
- promise.then()返回的新promise的结果状态由什么决定?
- 返回一个非promise值 resolved
- 抛出异常 rejected
- 返回一个promise
- 成功了 resolved
- 失败了 rejected
- pending pending
- 改变promise状态和指定回调函数谁先谁后?
- promise如何串连多个操作任务?
- promise异常传(穿)透?
- 中断promise链
自定义Promise
- 定义整体结构
- Promise构造函数的实现
- promise.then()/catch()的实现
- Promise.resolve()/reject()的实现
- Promise.all/race()的实现
- Promise.resolveDelay()/rejectDelay()的实现
- ES6 class版本