深入浅出+例子 总结JS(持续更新)

542 阅读2分钟

事件循环

先来看一道题:

async function foo() {
    console.log('foo')
}
async function bar() {
    console.log('bar start')
    await foo()
    console.log('bar end')
}
console.log('script start')
setTimeout(function () {
    console.log('setTimeout')
}, 0)
bar();
new Promise(function (resolve) {
    console.log('promise executor')
    resolve();
}).then(function () {
    console.log('promise then')
})
console.log('script end')

等同于

function bar({
  console.log('bar start')//同步代码中的宏任务
  new Promise(function(resolve){
    console.log('foo')//同步代码中的宏任务
    resolve()
  }).then(function(){
    console.log('bar end')//微任务
  })
  
}
console.log('script start')//同步代码中的宏任务
setTimeout(function ({
  console.log('setTimeout')//宏任务
}, 0)
bar();
new Promise(function (resolve{
  console.log('promise executor')//同步代码中的宏任务
  resolve();
}).then(function ({
  console.log('promise then')//微任务
})
console.log('script end')//同步代码中的宏任务

结果:

  • 先执行同步代码(宏任务),输出:
script start
bar start
foo
promise executor
script end
  • 再执行微任务,输出:
bar end
promise then
  • 执行当前队列所有微任务后,再执行宏任务,输出:
setTimeout
事件循环,如下图所示

image-20200401142428435

js 异步执行的运行机制

1、所有任务都在主线程上执行,形成一个执行栈。

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

3、异步任务分为宏任务和微任务。

执行流程 (宏任务 > 所有微任务 > 宏任务)

1、先执行 “执行栈”中同步任务(同步任务属于宏任务)完成,读取“任务队列”,执行有了结果的异步任务,进入执行栈并开始执行,

2、先执行完本次宏任务中的所有微任务

3、再执行下一个宏任务

4、再执行本宏任务中所有的微任务。

然后继续步骤3

setTimeout(() => {
  console.log('异步中宏任务1')
  new Promise(function (resolve) {
    resolve();
  }).then(function () {
    console.log('宏任务1中的微任务1')
  }).then(function () {
    console.log('宏任务1中的微任务2')
  }) 
}, 0);
setTimeout(() => {
  console.log('异步中宏任务2')
  new Promise(function (resolve) {
    resolve();
  }).then(function () {
    console.log('宏任务2中的微任务1')
  }).then(function () {
    console.log('宏任务2中的微任务2')
  }) 
}, 0);
setTimeout(() => {
  console.log('异步中宏任务3')
  new Promise(function (resolve) {
    resolve();
  }).then(function () {
    console.log('宏任务3中的微任务1')
  }).then(function () {
    console.log('宏任务3中的微任务2')
  }) 
}, 0);