Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

终于理解js的执行顺序:事件循环 #7

Open
liuduanyang opened this issue Jan 8, 2018 · 0 comments
Open

终于理解js的执行顺序:事件循环 #7

liuduanyang opened this issue Jan 8, 2018 · 0 comments

Comments

@liuduanyang
Copy link
Owner

liuduanyang commented Jan 8, 2018

主要记录异步代码顺序

WHATWG 规范:每一次事件循环,只处理一个 macrotask。待该 macrotask 完成后,所有的 microtask 会在同一次循环中处理。处理这些 microtask 时,还可以将更多的 microtask 入队,它们会一一执行,直到整个 microtask 队列处理完。

macrotask 与 microtask

任务队列又分为macrotask(宏任务)与microtask(微任务),二者均为队列

  • macrotask大概包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering
  • microtask大概包括:process.nextTick, Promise, Object.observe(已废弃), MutationObserver(html5新特性)

实例分析

下面用一段代码进行分析,猜猜输出顺序是什么?

console.log('script start') 

setTimeout(() => {  
  console.log('setTimeout 1')
  Promise.resolve().then(() => {
    console.log('promise 3')
  }).then(() => {
    console.log('promise 4')
  }).then(() => {
    setTimeout(() => {
      new Promise(resolve=>{
        console.log('promise 5');
        resolve();
      }).then(() => {
        console.log('promise 6')
      }).then(() => {
        setTimeout(()=>{console.log('setTimeout 3')},500);
      }).then(() => {
        console.log('promise 7')
      })
      console.log('setTimeout 2')
    }, 0)
  })
}, 0)

Promise.resolve().then(() => {  
  console.log('promise 1')
}).then(() => {
  console.log('promise 2')
})

代码多,是为了理解的更深刻,其实道理都是一样的,先放正确答案(在Chrome中得出)

script start
promise 1
promise 2
setTimeout 1
promise 3
promise 4
promise 5
setTimeout 2
promise 6
promise 7
setTimeout 3

事件循环每一轮称为一个tick,逐轮分析

tick 1:

先从macrotask队列的第一个元素开始执行,即运行整个script内的代码

console.log('script start') 是同步的,直接在主线程(执行线程)完成

继续执行,执行setTimeout(setTimeout1),将定时任务交给宿主环境(浏览器等)的工作线程执行,宿主环境的工作线程执行完毕后将回调函数加入到macrotask队列中

接下来执行Promise(Promise1),先同步执行resolve方法,决议后,将then内对应函数加入microtask队列

至此,同步代码已完成

开始检查microtask队列,存在一个元素(promise 1),开始执行,即promise 1,然后将promise 2加入到microtask队列中

再次检查队列,由于microtask队列存在元素,继续执行promise 2之后microtask为空 则调用下一个macrotask队列的元素 开始第二轮循环

tick 2:
... 同理 懒得打了

@liuduanyang liuduanyang changed the title 终于理解js的执行顺序 终于理解js的执行顺序:事件循环 Jan 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant