1.首先js是单线程的

所有的同步任务都是按顺序依次执行的,前面的执行完了之后才会执行后面的任务。遇到计算量大的代码就会阻塞在这里。下面的代码就是打印输出10000次,当循环走完了之后 才会走后面的代码,输出的时间是981ms

输出981ms

2.因为js是单线程的,所有的任务都需要按顺序执行,那如果我在执行过程中开启了一个定时器,定时器延迟10秒执行,后面的代码是不是要十秒之后才执行呢?

测试一下

输出的结果表示:定时器后面的代码先执行了,而定时器里面的代码再10秒后执行了

 这是为什么呢?

因为js虽然是单线程,但是我们并不需要所有的代码都要依次执行,避免一些不必要的阻塞。所以就引入了事件循环队列。引入了事件循环队列之后,就将js中所有的代码分成了两大类 ,一类是同步代码,另一类是异步代码。同步代码的执行顺序总是早于异步代码。 可以理解成,js从上到下依次执行,遇到同步的就直接执行,遇到异步的,就将异步的代码放到最后再执行。

下面代码的执行顺序是可以这样理解, 从上到下依次执行。先执行一号代码,是同步的,就直接输出。然后执行到二号代码,是个定时器,定时器是异步的,所以放到最后面再执行。然后执行三号代码,三号是同步的,直接输出。然后执行到四号代码,四号代码也是定时器,是异步的,所以放到最后(这个时候四号的异步代码是在二号的异步代码后面的)。然后执行到五号代码,直接输出。这个时候同步的代码已经全部执行完了,就开始执行刚刚放到最后面的二号代码和四号代码。

所以输出顺序是 同步1,同步2,同步3,异步1,异步2

输出结果

 

 而实际上,就是将异步的代码放入任务队列中去,等同步的代码执行完了之后,然后再去执行任务队列里的任务。

 

 哪些任务会进入任务队列呢(异步任务有哪些)?

定时器,ajax异步请求,promise.then里的东西 等等

任务队列又分成两个,一个是宏任务队列,一个是微任务队列。微任务队列里的任务要优先于宏任务队列里的任务

宏任务:定时器等

微任务:promise.then()里的代码,promise是同步的,ajax异步请求等

上面代码的执行顺序是(结合图一起看):

1.遇到了1号代码,是同步的,直接执行 输出1号,同步1。

2.遇到了二号代码,是个定时器,是宏任务,异步的。所以先不执行,放入宏任务队列

3.遇到三号代码的promise,是个微任务,先不执行,放入微任务队列

4.遇到5号代码,是同步的,直接执行 输出5号,同步2

 

5.这个时候同步代码执行完了,然后去任务队列里找任务执行。任务队列里有两个队列,一个是宏任务队列,里面有个定时器。还有一个微任务队列,里面有个promse成功的回调。因为微任务执行顺序是先于宏任务的,所以会先执行promise里面的代码

6.执行promise里的代码,遇到三号代码了,是同步的 直接执行 输出3号,微任务1

7.继续向下执行 遇到4号的定时器了,4号定时器是异步的,并且是宏任务,所以先不执行,放入宏任务队列

 

8.这个时候微任务队列里已经没有任务了,所以去执行宏任务队列里的任务。宏任务队列里先在有两个任务,一个是2号的定时器,一个是4号的定时器。

9.按顺序,先执行2号定时器里面的代码,里面的代码是同步的,直接执行 输出2号,宏任务1

 

10.执行完宏任务里的第一个任务之后(2号定时器),看一下微任务队列里还有没有任务,   有的话就继续执行微任务队列里的任务,没有的话就继续执行下一个宏任务队列里的任务。

11.我们这里微任务队列已经没有其他任务了,所以继续执行宏任务队列里的任务。执行4号定时器,里面的代码是同步的,所以直接执行,输出 4号,promise里的定时器

输出结果 

 

 

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐