js 事件循环机制

100 阅读2分钟

js线程

我们都知道js是单线程的,也就是说同一时间只能处理一件事情,那么我们所说的异步任务是怎么处理的呢,这就用到了js中的事件循环机制

知识点

首先我们要了解一下几个知识点:执行栈、同步任务、异步任务、任务队列

任务队列又分为:宏队列和微队列

执行栈

js的主线程上执行,形成一个执行栈,代码从上到下,依次入栈执行

当代码遇到一个同步任务时候,把同步任务放入执行栈进行执行

当遇到异步任务的时候,如果异步任务是微任务就放进微任务队列汇总等待执行,如果是宏任务就放进宏任务队列中等待执行,当全部的同步任务执行完之后,就去微任务队列中把微任务一个个推进执行栈中进行执行,直到所有微任务执行完,然后再去宏任务队列中把所有的宏任务推入执行栈中执行

如果在执行宏任务或者微任务的时候,还有同步或者异步任务还会按照上面的流程执行

    setTimeout(function () {
        console.log(1);
    });
    new Promise(function(resolve,reject){
        console.log(2)
        resolve(3)
    }).then(function(val){
        console.log(val);
    })
    console.log(4);
    
    //打印结果是 2,4,3,1

结果分析:遇到setTimeout宏任务,放进宏任务队列等待入栈,遇到promise,新建promise并且调用回调,这一步都是同步的所以直接入栈执行,而then的内的任务是异步的,并且是微任务,放进微任务队列等待执行,console.log(4);是一个同步任务,直接入栈执行,当console.log(4)执行完,没有其他同步任务,我们开始把微任务入栈执行,所以接下来执行的是console.log(val);,微任务也执行完了,就开始执行宏任务,从宏任务队列中去取出宏任务console.log(1);执行,这样结果就是如打印 2,4,3,1

    console.log(1);
    new Promise(function (resolve, reject) {
      console.log(2);
      resolve();
    }).then(function () {
      console.log(3);
      new Promise(function (resolve, reject) {
        console.log(8);
        resolve();
      }).then(function () {
        console.log(7);
        setTimeout(() => {
          console.log(13);
        });
      });
    });
    setTimeout(() => {
      console.log(4);
      new Promise(function (resolve, reject) {
        console.log(5);
        resolve();
      }).then(function () {
        console.log(6);
      });
    });
    
    // 打印顺序: 1 2 3 8 7 4 5 6 13