理论汇总

JavaScript中的异步和任务轮询

2018-03-06  本文已影响0人  萨默塞特酱

众所周知,我们JavaScript是一门单线程的语言,虽然借js是单线程的。但是我们的执行环境,也就是浏览器。它是多线程的。总得来说,浏览器分为以下几个线程。第一个就是我们的js线程,这个负责的是解释和执行我们的js代码
第二个是Gui,也就是负责绘制页面的。这个和Js线程是互斥的。也就是gs县城和gy县城不能同时执行。
第三个是处理网络请求的线程。
第四个是处理浏览器事件的线程。
这里面最重要的就是js线程。
然后gs是一门单线程的语言。为了实现异步,浏览器采用了一种叫做任务轮询的机制。那么gs是如何决定不同操作的执行顺序呢?
第一个是同步和异步。
同步代码永远比异步代码先执行。既然是引擎遇到同步操作时将同步操作推到一个调用栈里面。而遇到一波操作时江他们推到一个任务队列里面。当调用栈执行结束后就开始执行任务队列里面的代码。
第二个是异步的任务队列里面也分为两类
以nodejs执行环境为例。process.nexttick和promise属于microTask,setInterval和setTimeout属于macroTask。microTask队列执行完成后才会去执行macroTask队列。

setTimeout1 = setTimeout(function() {
    console.log('---1---')
  }, 0)

  setTimeout2 = setTimeout(function() {
    Promise.resolve()
      .then(() => {
        console.log('---2---')
      })
    console.log('---3---')
  }, 0)

  new Promise(function(resolve) {

    console.time("Promise")
    for (var i = 0; i < 1000000; i++) {
      i === (1000000 - 1) && resolve()
    }
    console.timeEnd("Promise")

  }).then(function() {
    console.log('---4---')
  });

  console.log('---5---')

js引擎从上到下解析代码,遇到setTimeout1setTimeout2,推入macroTask队列,继续执行.这里new Promise是一个同步操作,所以到打印出1自增到1000000的执行时间,然后将then回调推入microTask队列.然后是同步代码打印---5---.至此,同步代码已经执行完成.开始执行microTask队列中的任务,也就是console.log('---4---'),然后执行macroTask队列中的代码,首先是console.log('---1---'),然后setTimeout2中遇到Promise.then(),将其推入microTask队列中,继续执行console.log('---3---'),最后执行的是console.log('---2---')

上一篇下一篇

猜你喜欢

热点阅读