一道涉及宏任务和微任务的题,以及同步和异步

微任务、宏任务与Event-Loop

setTimeout(function(){
		    console.log('1')
});
new Promise(function(resolve){
		console.log('2');
        resolve();
}).then(function(){
	 console.log('3')
});
 
console.log('4'); 

请你给出这段代码的运行顺序。

同步异步我看过很多的讲解,大多都是要么你就一个setTimeout函数,要么就一个Promise函数。两个函数放到一起的我还真没见过。于是我就想:

settimeout肯定是异步的。 我也知道有一个event事件队列,你setTimeout没设置时间应该直接就进入这个队列了吧,然后就是Promise的回掉函数进入event队列。 答案应该是 2,4,1,3.

其实不然

首先说一下普通的异步函数的执行过程吧:
一道涉及宏任务和微任务的题,以及同步和异步_第1张图片

同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table事件表并注册函数。当指定的事情完成时,Event Table时间表会将这个函数移入事件队列Event Queue。主线程内的任务执行完毕为空,会去Event Queue事件队列读取对应的函数,进入主线程执行。上述过程会不断重复,也就是常说的Event Loop(事件循环)。

但是js异步有一个机制,就是遇到宏任务,先执行宏任务,将宏任务放入事件队列event queue,然后在执行微任务,将微任务放入事件队列event queue

最骚的是,这两个事件不放在同一个队列 (这个queue不是一个queue)。当你往外拿的时候先从微任务事件队列里拿这个回调函数,然后再从宏任务的事件队列queue上拿宏任务的回调函数。
再盗个图

一道涉及宏任务和微任务的题,以及同步和异步_第2张图片

宏任务一般是:包括整体代码script,setTimeout,setInterval。

微任务:Promise,process.nextTick。

记住就行了。然后回到开头代码。

因为settimeout是宏任务,
虽然先执行的,但是他被放到了宏任务的event queue里面,
然后代码继续往下检查看有没有微任务,检测到Promise的then函数把他放入了微任务序列。

等到主线进程的所有代码执行结束后。

先从微任务queue里拿回调函数,然后微任务事件队列queue空了后再从宏任务的事件队列queue拿函数。

所以正确的执行结果当然是:2,4,3,1。

同步和异步的区别

同步,可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是出于阻塞的,只有接收到返回的值或消息后才往下执行其他的命令。

异步,执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程,那么当系统接收到返回值或消息时,系统会自动触发委托的异步过程,从而完成一个完整的流程。

同步,就是实时处理(如打电话),比如服务器一接收客户端请求,马上响应,这样客户端可以在最短的时间内得到结果,但是如果多个客户端,或者一个客户端发出的请求很频繁,服务器无法同步处理,就会造成涌塞。

同步如打电话,通信双方不能断(我们是同时进行,同步),你一句我一句,这样的好处是,对方想表达的信息我马上能收到,但是,我在打着电话,我无法做别的事情。

异步,就是分时处理(如收发短信),服务器接收到客户端请求后并不是立即处理,而是等待服务器比较空闲的时候加以处理,可以避免涌塞。

异步如收发收短信,对比打电话,打电话我一定要在电话的旁边听着,保证双方都在线,而收发短信,对方不用保证此刻我一定在手机旁,同时,我也不用时刻留意手机有没有来短信。这样的话,我看着视频,然后来了短信,我就处理短信(也可以不处理),接着再看视频。

对于写程序,同步往往会阻塞,没有数据过来,我就等着,异步则不会阻塞,没数据来我干别的事,有数据来去处理这些数据。

同步在一定程度上可以看做是单线程,这个线程请求一个方法后就待这个方法给他回复,否则他不往下执行(死心眼)。

异步在一定程度上可以看做是多线程的(废话,一个线程怎么叫异步),请求一个方法后,就不管了,继续执行其他的方法。

你可能感兴趣的:(javascript,宏任务,微任务)