首先先看一道题目
console.log(‘1‘) setTimeout(function callback(){ console.log(‘2‘) }, 1000) new Promise((resolve, reject) => { console.log(‘3‘) resolve() }) .then(res => { console.log(‘4‘); }) console.log(‘5‘)
js是单线程的,也就是说是由上至下顺序执行的。但是引入一个新的概念,js中存在异步执行的代码,异步就是在另一个空间去执行这段代码不受之前同步代码的影响。
例如 setTimeout
函数就是异步的。异步执行的额外空间是哪里来的?那当然是JS所处的运行环境提供的了,而JS最主要的两个运行环境就是:浏览器 和 Node
首先浏览器会为代码在内存堆中分配内存,当每执行一段代码,都会把代码压入栈中,当执行完毕后出栈。
function one(a, b) { return a * b } function two(n) { return one(n, n) } function three(n) { let print= two(n) console.log(print) } three(5)
首先在堆中依次存入这四个代码片段,然后代码执行,three(n)、two(n)、one(n)依次入栈,执行过程中按顺序出栈完成这个执行过程。
浏览器中的各种 Web API 为异步的代码提供了一个单独的运行空间,当异步的代码运行完毕以后,会将代码中的回调送入到 Task Queue(任务队列)中去,等到调用栈空时,再将队列中的回调函数压入调用栈 中执行,等到栈空以及任务队列也为空时,调用栈仍然会不断检测任务队列中是否有代码需要执行,这一过程就是完整的Event Loop
console.log(‘1‘) setTimeout(function callback(){ console.log(‘2‘) }, 1000) console.log(‘3‘)
名称 | 举例(常用) |
---|---|
宏任务 | setTimeout 、setInterval 、UI rendering |
微任务 | promise 、requestAnimationFrame |
当宏任务和微任务都处于 Task Queue 中时,微任务的优先级大于宏任务,即先将微任务执行完,再执行宏任务。
既然区分了宏任务和微任务,那么存放它们的队列也就分为两种,分别为macro task queue(宏队列) 和 micro task queue(微队列)
根据相关规定,当调用栈为空时,对于这两个队列的检测情况步骤如下:
原文:https://www.cnblogs.com/qinxuhui/p/14041192.html