<1>概述
单线程模型:
js只在一个线程上运行,同时只能执行一个任务,其他任务排队等待.实际js引擎有多个线程,单个脚本只能在一个线程上运行(主线程),其他线程在后台配合.好处:实现简单,执行环境相对单纯.坏处:遇到耗时任务会延迟整个程序执行,如死循环造成浏览器假死(无响应),或读写外部数据服务器响应慢
\
事件循环机制:
cpu不管IO操作,挂起等待中的任务,先运行后面的任务,等IO操作返回结果(如Ajax操作从网络读取数据)再执行挂起的任务(为了利用多核cpu的计算能力,Web Worker标准允许js创建多个线程,但子线程完全受主线程控制且不得操作DOM,所以未改变js单线程的本质)
\
同步任务&异步任务:
同步任务指未被引擎挂起,在主线程上排队执行的任务,异步任务指被引擎挂起,不进入主线程而进入任务队列的任务,待引擎认为异步任务可以执行时(如Ajax操作从服务器得到结果)才会(采用回调函数的形式)进入主线程执行(变成同步任务),异步任务不具有“堵塞”效应
\
任务队列&事件循环:
存放等待程序处理的异步任务(若异步任务无回调函数就不会进入任务队列).事件循环:等同步任务执行完,引擎不停重复检查挂起的异步任务是否可以进入主线程执行的循环检查机制
\
异步操作模式:
1)回调函数:简单,容易理解和实现,但不利于代码阅读和维护,各部分高度耦合使得程序结构混乱,流程难以追踪(尤其多个回调函数嵌套的回调地狱),且每个任务只能指定一个回调函数
\
2)事件监听:
事件驱动模式,去耦合有利于实现模块化,可绑定多个事件,事件可指定多个回调函数.缺点是程序变成事件驱动型,流程不清晰
\
3)发布/订阅:
观察者模式,类似事件监听但更优,可查看“消息中心”存在多少信号及其多少订阅者,监控程序运的运行
\
异步操作的流程控制:
串行执行(耗时长)
并行执行(效率高,但容易耗尽系统资源拖慢运行速度)
串行并行结合(设置门槛避免过分占用系统资源,效率和资源的最佳平衡)
\
<2>定时器
定时器(timer)向任务队列添加定时任务
\
setTimeout()
返回整数表示定时器编号,参数1为函数或代码段字符串,参数2为推迟执行的毫秒数,省略则默认为0,其他参数作为要传入回调函数的参数,回调函数this指向全局环境,可套多一层匿名函数或bind指定this
\
setInterval()
无限次的定时执行,常见用途是实现轮询.参数2指定的是开始执行之间的间隔,并不考虑每次任务执行本身所消耗的时间,若耗时过久超过时间间隔则会在它结束后立即开始(如指定100ms,任务一耗时5ms,则结束后等95ms任务二开始,若105ms则需等105ms)为确保两次任务间固定间隔,可利用setTimeout()
\
clearTimeout(),clearInterval()
传入计数器编号取消对应的定时器(计数器返回连续整数,每次+1).该方法不会产生积累效应
\
debounce函数:防抖动
\
运行机制:
将指定代码移出本轮事件循环等到下一轮事件循环再检查是否到了指定时间去执行或继续等待(若同步任务执行很久且已到达预定时间会继续等待)
\
setTimeout(f,0):
同步任务处理完,下一轮事件循环一开始立即执行.可用于调整事件发生顺序(如调整冒泡事件父元素先触发,keypress监听取不到值),或处理计算量大耗时长的任务,分批处理减轻性能压力
\
<3>Promise对象
js异步操作解决方案,为异步操作提供统一接口,起到代理作用(proxy),充当异步操作与回调函数间的中介,使得异步操作具备同步操作的接口
\
状态:
异步操作未完成pending
异步操作成功fulfilled(已定型)
异步操作失败rejected(已定型)
一旦状态发生变化就凝固了,不会再有新的状态变化
\
构造函数:
生成Promise实例,传入一个回调函数,函数参数为resolve,reject.实例有then()方法
\
微任务:
Promise的回调函数属于异步任务,会在同步任务之后执行,但特殊在于它不是正常的异步任务而是微任务,它会追加到本轮事件循环,早于setTimeout执行