同步任务,异步任务,微任务,宏任务,事件循环(event Loop)(一天一个问题13)

tech2025-11-17  1

一、同步任务与异步任务

1.javascript是一门单线程语言,同一个时间只能做一件事(单线程与javascript引擎有关) 2.javascript里边任务分为同步任务和异步任务 3.同步任务会在主线程上排队执行,只有前一个任务执行完毕,才能执行后一个任务。异步任务不进入主线程,进入”任务队列”里边,只有”任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

1.1异步任务

1、定时器都是异步操作(setTimeout,setInterval) 2、事件绑定都是异步操作(onclick) 3、AJAX中一般我们都采取异步操作(也可以同步) 4、回调函数可以理解为异步(不是严谨的异步操作)(callback) 剩下的都是同步处理

1.2js如何实现异步操作(event Loop)

event Loop(事件循环),解决javascript单线程的问题。 例如:一个请求需要很久才会返回,单线程会阻碍程序的执行,这时就需要事件循环来解决阻碍问题。 event Loop:主线程上的同步任务执行完成之后,会推一个可执行的异步任务到主线程上执行,执行完成之后。再推一个异步任务到主线程上去执行,这样一个循环执行异步任务。

二、异步任务分类(宏任务和微任务)

2.1宏任务

定时器 事件绑定 ajax 回调函数 Node中fs可以进行异步的I/O操作

2.2微任务

Promise(async/await) => Promise并不是完全的同步,在promise中是同步任务,执行resolve或者reject回调的时候,此时是异步操作,会先将then/catch等放到微任务队列。当主栈完成后,才会再去调用resolve/reject方法执行 process.nextTick (node中实现的api,把当前任务放到主栈最后执行,当主栈执行完,先执行nextTick,再到等待队列中找)

2.3宏任务与微任务的执行

当主线程上的同步任务执行完成之后,先清理所有的微任务,再执行一个宏任务,清理所有的微任务。再执行一个宏任务,再清理所有的微任务(循环)。

三、题目

3.1
setTimeout(function(){ console.log('1'); }); new Promise(function(resolve){ console.log('2'); resolve(); }).then(function(){ console.log('3'); }); console.log('4'); 解读:setTimeout是一个宏任务。 new Promise()是一个构造函数同步任务,执行console.log(2) Promise().then()是一个微任务。 执行console.log(4)。 同步任务执行完成,执行所有的微任务console.log(2) 所有的微任务执行完成,执行一个同步任务console.log(1)。 输出:2,4,3,1
3.2
setTimeout(()=>{ new Promise(resolve =>{ resolve(); }).then(()=>{ console.log('test'); }); console.log(4); }); new Promise(resolve => { resolve(); console.log(1) }).then( () => { console.log(3); Promise.resolve().then(() => { console.log('before timeout'); }).then(() => { Promise.resolve().then(() => { console.log('also before timeout') }) }) }) console.log(2); 解读: 1.遇到setTimeout,异步宏任务,将() => {console.log(4)}放入宏任务队列中; 2.遇到new Promise,new Promise在实例化的过程中所执行的代码都是同步进行的,所以输出1; 3.而Promise.then中注册的回调才是异步执行的,将其放入微任务队列中 遇到同步任务console.log(2),输出2; 3.主线程中同步任务执行完从微任务队列中取出任务到主线程中,输出3,此微任务中又有微任务,Promise.resolve().then(微任务a).then(微任务b),将其依次放入微任务队列中; 从微任务队列中取出任务a到主线程中,输出 before timeout; 从微任务队列中取出任务b到主线程中,任务b又注册了一个微任务c,放入微任务队列中; 从微任务队列中取出任务c到主线程中,输出 also before timeout;微任务队列为空 4.从宏任务队列中取出任务到主线程,此任务中注册了一个微任务d,将其放入微任务队列中,接下来遇到输出4,宏任务队列为空 5.从微任务队列中取出任务d到主线程 ,输出test,微任务队列为空,结束~
3.3
console.log('1') setTimeout(()=>{ console.log('2'); new Promise(resolve=>{ console.log('3') resolve(); }).then(()=>{ console.log('4') }) },0) new Promise(resolve=>{ console.log('5') resolve(); }).then(()=>{ console.log('6') }) setTimeout(()=>{ console.log('7'); },0) setTimeout(()=>{ console.log('8'); new Promise(resolve=>{ console.log('9') resolve(); }).then(()=>{ console.log('10') }) },0) new Promise(resolve=>{ console.log('11') resolve(); }).then(()=>{ console.log('12') }) console.log('13'); //1,5,11,13,6,12,2,3,4,7,8,9,10

博客地址

最新回复(0)