- 异步模式特点:
- 不会等待这个任务结束才去开始下一个任务
- 对于耗时操作开启过后就立即去执行下一个任务
- 后续逻辑一般会通过回调函数的形式定义
- 示例:
```javascript
console.log(‘global begin’)
// 延时器
setTimeout(function timer1 () {
console.log(‘timer1 invoke’)
}, 1800)
// 延时器中又嵌套了一个延时器
setTimeout(function timer2 () {
console.log(‘timer2 invoke’)
setTimeout(function inner () {
}, 1000) }, 1000) console.log(‘global end’)console.log('inner invoke')
// global begin // global end // timer2 invoke // timer1 invoke // inner invoke ```
1. 开始执行,js内部引擎会将代码全部代码加载到js调用栈中
1. 在js调用栈中压入一个匿名调用(相当于把代码放入到一个匿名函数中去执行)
1. 依次执行每行代码
1. 对于console.log这样的同步api, 和同步是一样的先压入调用栈, 再执行, 最后弹出栈==> 控制台打印出 global begin
1. 将第一个setTimeOut压入调用栈, 但是这个函数的内部是异步调用, 所以需要关心内部环境做了什么事情(为timer函数开启了一个倒计时器, 然后单独放到一边), 这个倒计时器是单独工作的,并不会对JS的单线程模式产生影响, 所以说从调用开始过后就开始倒数了. webApi中记录1.8s
1. 第二个setTimeOut, 先压入调用栈, 再执行, 最后弹出栈. webApi中记录1s
1. console.log这样的同步api, 和同步是一样的先压入调用栈, 再执行, 最后弹出栈==> 控制台打印出 global end
1. 到此为止,调用栈已全部清空, Event loop发挥作用(负责监听调用栈和消息队列)
1. 当调用栈中的任务全部结束时, Event loop就会从消息队列中取出第一个回调函数压入到调用栈,但是当现在,消息队列中还什么都没有, 所以代码执行到现在算是先暂停下来
1. 一秒钟之后, web Api中的延迟为1s的timer2会被放到消息队列的第一位 1.8s后, web Api中的延迟为1.8s的timer1会被放到消息队列的第二位
1. 当消息队列发生变化时, Event loop就会将消息队列中的第一位timer2取出来压入调用栈中, 开启了新的执行==> 控制台打印出 timer2 invoke
1. Event loop就会将消息队列中的timer1取出来压入调用栈中, 继续执行==> 控制台打印出 timer1 invoke , webApi中记录1s, 调用栈清空,
1. 一秒钟之后, web Api中的延迟为1s的inner会被放到消息队列的第一位
1. 消息队列发生变化, Event loop将消息队列中的第一位inner取出来压入调用栈中, 开启了新的执行==> 控制台打印出 inner invoke