首页 > 技术文章 > js事件的执行机制(eventloop)

yaya-003 2020-05-12 11:50 原文

一、js的内存模型

 

 

 

二、js代码执行机制:

  • 所有同步任务都在主线程上的栈中执行。

  • 主线程之外,还存在一个"任务队列"(task queue)只要异步任务有了运行结果,就在"任务队列"之中放置一个事件

  • 一旦"栈"中的所有同步任务执行完毕,系统就会读取"任务队列",选择出需要首先执行的任务(由浏览器决定,并不按序)。

三、宏任务与微任务:

  1. MacroTask(宏观Task) setTimeout, setInterval, , requestAnimationFrame(请求动画), I/O

  2. MicroTask(微观任务) process.nextTick, Promise, Object.observe, MutationObserver

  3. 先同步 再取出第一个宏任务执行 所有的相关微任务总会在下一个宏任务之前全部执行完毕 如果遇见 就 先微后宏

 

案例一:(在主线程上添加宏任务)

    console.log(1)
    setTimeout(function () {
      console.log(2);
    },0)
    console.log(3)  //1 3 2

先看代码:一个打印,一个定时器,一个打印

因为定时器是异步操作,又是宏任务,所以先执行第一个打印,接着将setTimeout放入宏任务队列,接着执行第二个打印再执行宏任务队列中的setTimeout

案例二:(在主线程上添加微任务)

   console.log(1)
    new Promise(function(resolve,reject){
        console.log('2')
        resolve()
    }).then(function(){
      console.log(3)
    })
    console.log(4)  //1 2 4 3

先看代码:一个打印,一个new promise,一个promise.then,一个打印

因为new promise会立即执行,promise.then是异步操作且是微任务

所以,先执行第一个打印,执行new Promise将promise.then放入微任务队列接着执行第二个打印,再执行微任务队列中的promise.then

案例三:(红任务中创建微任务)

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

    setTimeout(function () {
      console.log('7');
      new Promise(function (resolve) {
        console.log('8');
        resolve();
      }).then(function () {
        console.log('9')
      })
      console.log('10')
    },0)
   
    console.log('11')  
// 1  5 11 6 2 3  4 7 8  10 9

先看代码:一个打印,第一个定时器,一个new promise,一个promise.then,第二个定时器,一个打印

定时器是异步操作,又是宏任务,promise.then是异步操作且是微任务

所以,先执行第一个打印(1),将第一个定时器放入宏任务队列,执行new Promise(5),将promise.then放入微任务队列,将第二个定时器放入宏任务队列,执行打印(11);

主线程上的代码执行完毕后,看是否有微任务?此时:微任务队列中有一个promise.then,执行它(6);微任务执行完毕看宏任务队列;

此时宏任务队列中两个定时器,延时都是0秒,所以按顺序执行就ok,先执行第一个定时器

第一个定时器中:一个打印,一个mew promise,一个promise.then(微任务);(宏任务中包含微任务,一定要将宏任务中的微任务执行完,再去执行下一个宏任务)

      先执行打印(2),再执行new promise(3),再执行promise.then(4);第一个宏任务执行完,执行第二个宏任务(第二个定时器)

第二个定时器中:一个打印,一个new promise,一个promise.then(微任务),一个打印

      先执行第一个打印(7),再执行new promise(8),再执行第二个打印(10),在执行promise.then(9) 

案例四:(微任务中创建宏任务)

 

   new Promise((resolve) => {
      console.log("1")
      resolve()
    }).then(() => {
      console.log("2")
      setTimeout(() => {
        console.log("3")
      },0)
    })
    setTimeout(() => {
      console.log("4")
    },1000)
    console.log("5")  //1 5 2 3 4 

 

先看代码:一个new promise,(一个then,一个定时器(0秒)),一个定时器(1秒),一个打印 微任务中有宏任务,则将宏任务放入宏任务队列任务中

先执行new promise(1),再将promise.then放入微任务队列,将定时器放入宏任务队列(0秒),将定时器放入宏任务队列(1秒),执行打印(5)

接着看微任务队列,执行promise.then(2);微任务队列中都执行完再看宏任务队列

宏任务队列中两个定时器,一个延时0秒,一个延时1秒,所以先执行延时0秒的那个

第一个定时器:执行(3);

第二个定时器:执行(4)

 

推荐阅读