事件循环
- JavaScript是单线程,非阻塞的
- 浏览器的事件循环
- 执行栈和事件队列
- 宏任务和微任务
- node环境下的事件循环
- 和浏览器环境有何不同
- 事件循环模型
- 宏任务和微任务
1.JavaScript是单线程,非阻塞的
- 单线程:JavaScript主要用途是与用户交互,以及操作DOM。如果是多线程会有很多复杂的问题,例如两个线程同时操作DOM,一个删除当前DOM,一个操作当前DOM,所以为了避免这个问题,JS是单线程的。
- 非阻塞:通过even loop实现
2.浏览器的事件循环
1.执行栈和事件队列
-
执行栈:(主线程)同步代码的执行,按顺序添加到执行栈中
-
事件队列:(任务队列)异步代码的执行,遇到异步事件不会等待它返回结果,而是将这个事件挂起,继续执行执行栈(主线程)中的其他任务。当异步事件返回结果,将它放到事件队列中,被放入事件队列不会立刻执行回调,而是等待当前执行栈(主线程)中所有任务执行完毕,主线程空闲状态,主线程会去查找事件队列中是否有任务,如果有,则取出排在第一的事件,并把这个事件对应的回调放到执行栈中,然后执行其中的同步代码。
-
事件循环:代码执时分为同步任务和异步任务,同步任务直接进入主线程,异步任务进入任务队列。主线程任务执行完毕,从任务队列读取任务推入到主线程,重复该过程直到任务执行完毕,重复的过程成为事件循环。
2.宏任务和微任务
不同的异步任务被分为:宏任务和微任务
-
宏任务:script、setTimeout()、setInterval()、postMesssage、I/O、UI交互事件
-
微任务:new Promise().then()
3.运行机制
-
异步任务的返回结果会被放到一个任务队列中,根据异步事件的类型,会被放到对应的宏任务和微任务中。
-
当前执行栈为空时,主线程会查看微任务队列是否有事件存在
- 存在,依次执行队列中的事件对应的回调,直到微任务队列为空,然后去宏任务队列中取出最前面的事件,把当前的回调加到当前当前指向栈。
- 不存在,去宏任务队列中取出一个事件并把对应的回调加入当前执行栈
- 当前执行栈执行完毕后会立刻处理所有微任务队列中的事件,然后再去宏任务中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行。
总结:
在事件循环中,每进行一次循环操作成为tick,每一次tick的任务步骤如下:
- 执行一个宏任务(栈中没有就中事件队列中获取)
- 执行过程中如果遇到微任务,就将它添加到为任务的任务队列中
- 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
- 当前宏任务执行完毕,开始检查渲染
- 渲染完毕之后,开始下一个宏任务
执行顺序:
- 执行宏任务,然后执行宏任务产生的微任务,若微任务在执行过程中产生了新的微任务,则继续执行微任务,微任务执行完毕后,再回到宏任务中进行下一轮循环。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END