宏任务与微任务

115 阅读3分钟

宏任务与微任务

Event Loop:事件循环

我们都知道 Js 是单线程的,但是一些高耗时操作就带来了进程阻塞问题。为了解决这个问题,Js 有两种任务的执行模式:同步模式(Synchronous)和异步模式(Asynchronous)

异步模式

在异步模式下,创建异步任务主要分为宏任务与微任务两种,宏任务是由宿主(浏览器、Node)发起的,而微任务由 JS 自身发起。微任务比宏任务的执行时间要早

异步任务:不进入主线程,而是进入任务队列,当主线程中的任务执行完毕,就从任务队列中取出任务放进主线程中来进行执行。由于主线程不断重复的获得任务、执行任务、再获取再执行,所以这种机制被叫做事件循环(Event Loop)

任务队列和Event Loop(事件循环)

1)所有的同步任务都在主线程上执行,行成一个执行栈。

2)除了主线程之外,还存在一个任务列队,只要异步任务有了运行结果,就在任务列队中植入一个时间标记。

3)主线程完成所有任务(执行栈清空),就会读取任务列队,先执行微任务队列再执行宏任务队列。

4)重复上面三步。

    只要主线程空了,就会读取任务列队,这就是js的运行机制,也被称为 event loop(事件循环)。

宏任务:SettimeOut()setIntervalI/Oscript(整体代码块)DOM事件Ajax

微任务:Promise.[ then/catch/finally ]async/await

注意:Promise本身是属于同步任务

栗子:

                setTimeout(function(){
			console.log('setTimeout') 
		},0) 		
		//同步
		console.log('script start')	
		async function async1(){
			//同步
			console.log('async1 start');
			await async2()
			//异步
			console.log('async1 end')
		}	
		async function async2(){
			//同步
			console.log('async2 end')
		}	
		//微任务
		new Promise(function(resolve){
			//同步
			console.log('promise')
			for (var i = 0; i <10000; i++) {
				if (i === 10) {
					console.log("3")
				}
				i == 9999 && resolve('4')
			}
			resolve();
		}).then(function(val){
			console.log(val)
			//异步
			console.log('promise1')
		}).then(function(res){
			console.log(res)
			console.log('promise2')
		})	
		//微任务
		async1(); 	
		//同步
		console.log('script end')

执行步骤

1) 事件任务从宏任务(macrostack)队列开始,此时宏任务队列中只有一个script(整体代码)任务
,从宏任务队列中取一个任务来执行

2)首先遇到 setTimeout 添加到宏任务队列中

3) 执行同步代码 console.log('script start') 输出 script start

4)遇到 两个 async(异步)Function 未调用 暂不放入微任务队列。

5)遇到 new Promise()  因为promise属于同步任务 进入执行
    5.1)执行console.log('promise') 输出 promise
    5.2)执行for循环,i=1时  执行console.log("3")  输出 3
    5.3)执行for循环,i=9999时  执行resolve('4'), 触发.then, .then属于微任务 放入微任务队列
    5.4)执行resolve()触发.then, .then属于微任务 放入微任务队列

6)遇到 async1()  同步调用, 进入async1()
    6.1)执行console.log('async1 start'); 输出 async1 start
    6.2)执行await async2()   由于await 所以是同步执行 进入async2() 
        6.2.1) 执行console.log('async2 end'); 输出 async2 end
    6.3)遇到 console.log('async1 end') 属于异步 加入微任务队列

7) 遇到console.log('script end') 输出 script end  到此同步任务执行完毕

8) 取出微任务队列中 所有内容 .then和 asyn加入的console.log('async1 end') 执行
    8.1) 先执行resolve('4')的.then  输出 4  promise1
    8.2) 执行resolve()的.then 输出  undefined promise2 
    8.2) 执行asyn加入的console.log('async1 end') 输出  async1 end (async1 输出可能会在undefined之前) 到此微任务执行完毕
    
9) 去除宏任务,按照存放顺序
    9.1) 执行 settimeout() 输出 setTimeout
    
    

图片.png