1. 进程和线程
- 进程是操作系统中资源分配的基本单位。而线程则是操作系统中调度执行的基本单位。把操作系统比喻成一个商场,进程则相当于商场里面的某一个店铺。店铺面积大小则就是相当于操作系统分配的资源大小。线程则是相当于该店铺的一个店员。注意:一个进程可以有多个线程。
2. JavaScript和浏览器
我们应该都知道JavaScript是一门单线程语言,也就是相当于上面所提到的一个店员。既然JavaScript是单线程语言,那又何来异步这一说法呢?
因为JavaScript运行在浏览器环境中,而浏览器的渲染进程是多线程的。具体线程如下:
- GUI渲染线程
- JS引擎线程
- 事件触发线程
- 定时触发器线程
- 异步http请求线程
这里需要注意的地方就是:GUI渲染线程和JS引擎线程是互斥的,及两者之间只有一者运行知道运行结束令者会被立即唤起(这里我们可以利用起来解决白屏时间过长的问题)。
3. eventloop(时间循环)
浏览器的时间循环分为同步任务和异步任务,而异步任务里又分为宏队列任务和微队列任务。
宏队列任务: 常见的有script(代码块),setTimeout(计时器),setInterval(定时器)、I/O、UI交互事件、setImmediate(nodejs环境下的)。
注:script标签为宏任务
微队列任务: 常见的有promise.then()(注意promise后的resolve并非微队列只有.then()里面才属于微队列)、MutationObserver(html5新特新)、process.nextTick(node环境)。 若同时存在promise和nextTick,则先执行nextTick。
事件循环机制: 当有异步任务被压入异步任务队列时候,javascript会将这些异步任务分为宏任务和微任务两个新的队列。然后,在所有同步任务执行完毕之后,异步任务会优先执行所有已经存在任务队列中的微任务。在所有的微任务执行完毕之后,再去宏任务队列中执行一个宏任务,执行完一个宏任务之后会再去微任务队列中检查是否有新的微任务,有则全部执行,再回到宏任务队列执行一个宏任务,以此循环。这一套流程,就是事件循环(event loop)
总结:
JavaScript执行顺序为
1、立即执行非微队列或者宏队列(延时队列),任务,遇到微队列任务放到微队列,遇到延时队列任务放到延时队列。
2、当所有的非微队列或者宏队列(延时队列)执行完毕,进入微队列任务,重复1、2。
3、当所有的微队列任务执行完毕时,进入宏队列任务,重复1、2、3。