JS中的进程、线程、任务队列、事件循环、宏任务、微任务、执行栈等概念理解
javascript中有很多需要知道的概念,尤其是标题中列出来的这些,今天就来过一下这些概念。
一、进程和线程
浏览器的每一个tab页可以看做是浏览器内核进程,每个进程下面会有多个线程来互相配合完成任务
比如 GUI线程、JS引擎线程、网络线程、定时器线程等
二、任务队列
任务队列可以当做是一个个的对调任务,当主线程的任务完成后,就开始执行任务队列中的任务(如果当前任务队列中再添加了新的异步任务,则其回调函数会放在之后的任务队列中)
三、事件循环
异步任务执行后,其回调会放到任务队列中。当主线程任务执行结束后,就去任务队列中捞接下来要做的任务,放到主线程中执行,直到任务全部结束。如果无新的任务可做,浏览器处于等待状态,知道新的外部输入、事件触发,这样一个循环过程称为事件循环。
四、宏任务和微任务
任务队列中有两种任务,一种是宏任务一种是微任务。具体概念我也没有查到,但是可以这样去理解,微任务就是执行完当前主线程任务后就要马上执行的任务,宏任务则是要放到下一次的事件循环中的主线程中的任务。
一般的宏任务有setTimeout和setInterval
微任务则有promise、process.nextTick等
五、执行栈
执行栈是解释器追踪函数执行流的一种机制。当引擎第一次遇到js代码时,会产生一个全局执行上下文压入执行栈,每遇到一个函数调用,就往栈中压入一个新的上下文。引擎执行栈顶的函数后则弹出当前执行上下文直至函数依次执行完毕并回到全局的上下文。
测试
有兴趣的同学可以试试下面代码的输出顺序
setTimeout(function () {
console.log('1')
});
new Promise(function (resolve) {
console.log('2');
resolve();
}).then(function () {
console.log('3')
setTimeout(function () {
console.log('5')
});
});
console.log('4');
遇到第一个settimeout时,先把整体代码块放到第一个宏任务中,遇到promise,先执行内部的代码,把then中的代码放到为任务中。遇到console.log(4)在主线程中直接执行。之后先从微任务中捞取任务执行 console.log(3)并把后面的setTimeout放到下一个宏任务队列(第二个)中。然后从当前宏任务队列中捞取要执行的代码,打印1。然后开始到下一个事件循环,把宏任务的代码捞出来执行。
所以顺序是24315