浏览器 Eventloop

吐槽君 分类:javascript

执行顺序

阮一峰老师谈Event loop

  1. 所有的同步任务都在主线程上执行,形成一个执行栈(execution context stack)
  2. 主线程之外,还有一个任务队列(task queue)
  3. 一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列,里面的异步任务就会结束等待状态,进入执行栈,开始执行
  4. 主线程会不断的重复上面的三部内容

个人理解

在一次事件轮询中,有一个主线程,形成一个执行栈,还有一个任务队列,和一个微任务队列。
代码在主线程当中,当遇到同步代码,就把它执行完;如果遇到微任务,就把它放入微任务队列中,当遇到异步宏任务时,就把它放入宏任务队列。当同步任务执行完后,会检查是否存在微任务,如果有就把微任务队列清空。至此,本次事件轮询结束。然后执行栈,去取任务队列里面的异步宏任务,执行里面的代码,重复以上操作....直到代码执行完毕

eventloop.jpg

微任务: process.nextTick, promise, MutationObserver

宏任务: script, 同步代码属于宏任务
settimeout, setInterval, setImmediate, I/O, UI-rendering

执行栈

执行栈可以认为是一个存储函数调用的栈结构

进程,线程

进程:CPU在运行指令及加载和保存上下文所需要的时间
线程:线程是进程中更小的单位,描述了执行一段指令所需要的时间
JS是单线程语言

Js单线程带来什么好处 ?

节省内存,更安全的渲染

async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
   }
   async function async2() {
    console.log('async2 start');
    return new Promise((resolve, reject) => {
     resolve();
     console.log('async2 promise');
    })
   }
   console.log('script start');

   setTimeout(function() {
    console.log('setTimeout');
   }, 0);  // 去到宏任务队列
   
   async1();
   new Promise(function(resolve) {
    console.log('promise1');
    resolve();
   }).then(function() { // 微任务队列
    console.log('promise2');
   }).then(function() { // 微任务队列
    console.log('promise3');
   });
   console.log('script end');
   
 // script start, async1 start, async2 start ,async2 promise,promise1,script end,  
 //promise2,promise3,setTimeout
 

async await

在函数前声明async,意味着会返回一个promise对象。async函数内部return语句返回的值,会成为then方法回调函数的参数。也就是说,写了async就相当于是promise里面执行了resolve(),它代表的一定是成功的情况。当async内部有await时,await这条语句的内容会立即执行,但是await之后的代码会被阻塞。

async function async1() {
   console.log('async1 start');
   await async2();
   console.log('async1 end');
  }
 

(也就是指async2函数会被立即执行,但是后面的console.log('async1 end')会被阻塞,它会去到下一次事件轮询的微任务队列)

然后跳出当前函数,去执行外部的同步代码。当同步代码执行完,去查看当前异步任务中的微任务队列,清空微任务队列后,执行异步中的宏任务队列。至此一次事件轮询结束。再进入下一次事件轮询,里面有settimeout,去到异步宏任务,将再次去到下一次事件轮询,而这个console.log('async1 end')处于这次事件轮询的微任务队列,会被执行。(至于为什么会在这次事件轮询的微任务队列,是await导致的,它实际上是在promise.then()里面的,这里涉及到generator的用法),然后再次去到下一次事件轮询,执行setTimeout里面的内容。

回复

我来回复
  • 暂无回复内容