Event Loop,事件环,线程进程。这些概念对初识前端的同窗来讲可能会一头雾水。并且运行js代码的运行环境除了浏览器还有node。所以不一样环境处理Event Loop又变得不一样,十分容易混淆。若是你有这样的疑问。下文将给你一个清晰的解释。javascript
首先咱们简化一下概念,把进程,线程,事件环,这些概念梳理一下。清晰了概念后面用到的时候就会有共鸣。html
拿出在教科书里的概念:前端
一、调度:线程做为调度和分配的基本单位,进程做为拥有资源的基本单位;java
二、并发性:不只进程之间能够并发执行,同一个进程的多个线程之间也可并发执行;node
三、拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但能够访问隶属于进程的资源;git
四、系统开销:在建立或撤消进程时,因为系统都要为之分配和回收资源,致使系统的开销明显大于建立或撤消线程时的开销。es6
进程和线程的关系:github
接下来看一下浏览器引擎(进程)中包含哪些线程chrome
注意
:UI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起(至关于被冻结了),UI更新会被保存在一个队列中等到JS引擎空闲时当即被执行。后端
一样注意
:UI渲染线程与JS引擎线程是互斥的,因此若是JS执行的时间过长,这样就会形成页面的渲染不连贯,致使页面渲染加载阻塞。
注意
:因为JS的单线程关系,因此这些待处理队列中的事件都得排队等待JS引擎处理(当JS引擎空闲时才会去执行)
注意
:W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms。
以上线程,每一个拿出来均可以详细的说上一篇。Event Loop涉及到的JS引擎的一些运行机制的分析。咱们能够将这些线程理解为,
setTimeout(function(){
console.log(0)
},500)
setTimeout(function(){
console.log(1)
},1000)
setTimeout(function(){
console.log(2)
},2000)
for(;;){
}
复制代码
上面这段代码用于不会有输出,同步代码死循环阻塞了执行栈。虽然定时后回调加入执行队列,可是异永远不会执行。
题目二:
setTimeout(function(){
console.log('setTimeout1');
Promise.resolve().then(()=>{
console.log('then1');
});
},0)
Promise.resolve().then(()=>{
console.log('then2');
Promise.resolve().then(()=>{
console.log('then3');
})
setTimeout(function(){
console.log('setTimeout2');
},0)
})
复制代码
答案:then2 then3 setTimeout1 then1 setTimeout2
首先在题目中出现了es6的promise,他的出现让原来咱们理解的__事件环产生了一些不一样__。 为何呢?由于Promise里有了一个一个新的概念:microtask 此时JS中分为__两种任务类型__:macrotask和microtask,在ECMAScript中,microtask称为jobs,macrotask可称为task
首先说明,是以__浏览器为处理环境__下的执行逻辑 浏览器环境下的微任务和宏任务有哪些 宏任务:setTimeout setImmediate MessageChannel 微任务:Promise.then MutationObserver
记住两点:
而后题目入手分析宏任务和微任务的执行
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。他的目标就是解析js代码,让他能运行起来。
和浏览器环境下相似,他有一个解析js的主线程,其余线程做为辅助,可是由于不涉及操做dom,ui线程就不存在了。(各个线程的概念参考浏览器环境下的线程)
单线程在浏览器运行环境中的弊端体如今阻塞页面执行。
那么node做为后端服务,单线程有什么利弊?
优势:
事件环的总体仍是不变的,执行栈,消息队列,api。不一样的是,node下的消息队列有所不一样
从一个题目入手感觉一下node环境和浏览器环境下的不一样
setTimeout(() => {
console.log('timeout1');
Promise.resolve().then(() => {
console.log('promise');
});
}, 0)
setTimeout(() => {
console.log('timeout2');
}, 0)
复制代码
浏览器下的结果:timeout1 promise timeout2
node下的结果:timout1 timeout2 promise
node环境下的微任务和宏任务有哪些 宏任务:setTimeout setImmediate 微任务:Promise.then process.nextTick
题目三能够很好的分析node环境下的任务执行 node环境下运行流程
注意
:一样是微任务,process.nextTick,优于promise.then先执行
Promise.resolve().then(() => {
console.log('then')
})
process.nextTick(() => {
console.log('nextTick')
});
//nextTick then
复制代码
注意
:一样是宏任务,setTimeout和setImediate执行的前后顺序是不肯定的,依赖于执行栈执行的速度。
setImmediate(function () {
console.log('setImmediate')
});
setTimeout(function () {
console.log('setTimeout')
}, 0); // ->4
复制代码
let fs = require('fs');
fs.readFile('./gitignore', function () { // io的下一个事件队列是check阶段
setImmediate(function () {
console.log('setImmediate')
});
setTimeout(function () {
console.log('setTimeout')
}, 0); // ->4
})
复制代码
给个提示,读文件是io操做,io执行以后首先要check,check以后或没有check内容再去检查定时队列。 那么结果就留给你们自行分析了。
但愿这篇文章能给初识js的你一个清晰的大框,也是梳理我本身的知识。可能我理解的也很粗浅,有错误的地方,但愿你们帮忙指正。