教程
js运行机制同步与异步(宏任务与微任务)
118

js运行机制

众所周知,javascript的最大特点就是单线程,同一时间追能做同一件事,所以为了防止主线程的阻塞,在代码执行时分为同步任务异步任务,所有的同步任务在主线程上执行,形成执行栈,而异步任务形成一个新的任务队列,又把任务队列中的异步任务分为宏任务微任务,虽然他们都在任务队列中,但是它们却在不同的队列中,微任务的执行优先级大于宏任务,他们的结构如图所示。

宏任务

浏览器为了能够使得JS内部任务与DOM任务能够有序的执行,会在一个任务执行结束后,在下一个任务执行开始前,对页面进行重新渲染

常见的宏任务主要有 定时器ajax读取文件dom事件setImmediate(Node.js 环境)requestAnimationFrameI/0UI交互postMessage

微任务

需要在当前 同步任务 执行结束后立即执行的任务,比如对一系列动作做出反馈,或者是需要异步的执行任务而又不需要分配一个新的任务,这样便可以减小一点性能的开销

常见的微任务包括Promise.thenObject.observeMutationObserverprocess.nextTick(Node.js 环境)

运行机制

代码案例

1.定时器因为是异步宏任务,所以先执行主线程的打印语句,主线程没有任务再从宏任务任务队列中取出定时器执行

 setTimeout(() => {
        console.log("setTimeout qz");
      }, 0);
      console.log("qz");
//输出结果
//qz
//setTimeout qz

2.先执行主线程的同步任务,构造函数是同步任务,先打印aaa语句,在打印qz,主线程的语句没了,然后查看异步线程,promise.then是微任务,所以先打印.then和bbb,定时器宏任务最后执行

 Promise.resolve().then((value) => console.log(".then"));
      setTimeout(() => {
        console.log("定时器");
      }, 0);
      new Promise((resolve) => {
        console.log("aaa");
        resolve();
      }).then((res) => {
        console.log("bbb");
      });
      console.log("qz");
//输出结果
//aaa
//qz
//.then
//bbb
//定时器

3,先执行主线程内容,打印qqzz,aaa,qz主线程没内容,开始执行异步队列中为微任务,打印.then,bbb,此时微任务没了,开始执行宏任务,打印定时器,因为定时器中含有微任务和宏任务,所以继续打印ccc,再执行定时器中的宏任务ddd,最后打印eee

Promise.resolve().then((value) => console.log(".then"));

      setTimeout(() => {
        console.log("定时器");

        new Promise((resolve) => {
          console.log("ccc");
          resolve();
        }).then((res) => {
          console.log("ddd");
        });
        
      }, 0);

      console.log("qqzz");

      new Promise((resolve) => {
        console.log("aaa");

        setTimeout(() => {
          console.log("eee");
        }, 0);

        resolve();
      }).then((res) => {
        console.log("bbb");
      });

      console.log("qz");
      //输出结果
      //qqzz
      //aaa
      //qz
      //.then
      //bbb
      //定时器
      //ccc
      //ddd
      //eee

总结

1.主线程读取JS代码,环境为同步环境,将同步任务分为对应的堆和执行栈

2.同时,主线程执行中遇到异步任务,会将其推给异步进程进行处理,webAPI

3.异步任务对异步任务进行处理,遵循先进先出的顺序依次推入任务队列(异步队列)

4.主线程执行完同步队列之后,查询任务队列,按顺序执行微任务,待微任务执行完毕后执行宏任务

5.形成事件循环

执行顺序 : 同步任务 > process.nextTick > 微任务 > 宏任务 > seImmediate


  • 上一篇
  • 下一篇
  • 添加评论
    welcome to qiangzai blog