入门异步编程

js如何执行

  • 从前到后,一行一行执行
  • 如果某一行执行报错,则停止下面代码的执行
  • 先把同步代码执行完,再执行异步
    // 事例
    console.log("Hi");
    setTimeout(function cb1() {
        console.log("cb1");
    })
    console.log("Bye")
    // 执行结果  Hi Bye cb1
复制代码

eventLoop001_2021-06-13_10-26-18.png

js的异步任务在任务队列中排队,同步任务执行完毕,由于事件循环的作用把其推入到函数调用栈中执行

事件循环和任务队列

事件循环过程

  • 如Call Stack为空(即同步代码执行完)Event Loop开始工作
  • 轮询查找Callback Queue ,如有则移动到Call Stack 执行
  • 然后继续轮询查找(永动机一样)

宏任务和微任务

  • 宏任务: setTimeout , setInterval , Ajax ,DOM事件
  • 微任务:Promise , async/await
  • 微任务执行时机比宏任务要早

宏任务和微任务的执行流程.png

event Loop 和 DOM 渲染

eventLoop和dom渲染.png

宏任务和微任务以及dom渲染事如何运作的

  • 每次Call Stack清空(即每次轮询结束),即同步任务执行完
  • 每次执行完所有的同步任务后,会在任务队列中取出异步任务,先将所有微任务执行完成后
  • 所有微任务执行完成,是DOM重新渲染的机会,DOM结构如有改变则重新渲染
  • 最后才会去执行宏任务

eventLoop和dom渲染001.png

eventLoop和dom渲染002.png

从event loop解释,为何微任务执行更早

  • 微任务是ES6语法规定的
  • 宏任务是由浏览器规定的

promise then 的回调函数是在什么时候进入微任务队列的

  • 关键在于,then 是在 resolve 之前被调用的,还是 resolve 之后呢
  • then 在 resolve 之前,then 不会加微任务,而是缓存起来,resolve 看到缓存里又 then 的回调,于是加微任务
  • resolve 在 then 之前,resolve 的时候还没有任何回调要执行,自然不会加微任务。then 的时候发现已经 fullfilled ,于是直接加微任务
  • 也就是说,他们都有可能加,也都有可能不加,就看调用时的 promise 的状态了
  • 在我的理解里,Promise 的实现中,then只会把回调放到一个数组里保存,所以我认为,reslove 后,才会进入微任务队列,存放callback 只是一个存放的操作

参考习题

第一题
async function fn() {
    return 100
  }
  (async function() {
    const a = fn();
    const b = await fn();
    console.log(a, b)
  })();
  (async function() {
    console.log('hehe')
  })()
  // hehe  Promise { 100 } 100


// #######################################################

第二题
console.log('1');
async function async1() {
  console.log('2');
  await async2();
  console.log('3');
}
async function async2() {
  console.log('4');
}

process.nextTick(function() {
  console.log('5');
})

setTimeout(function() {
  console.log('6');
  process.nextTick(function() {
    console.log('7');
  })
  new Promise(function(resolve) {
    console.log('8');
    resolve();
  }).then(function() {
    console.log('9')
  })
})

async1();

new Promise(function(resolve) {
  console.log('10');
  resolve();
}).then(function() {
  console.log('11');
});
console.log('12');
// 1
// 2
// 4
// 10
// 12
// 5
// 3
// 11
// 6
// 8
// 7
// 9

// #######################################################

第三题
new Promise(resolve => {
  resolve();
}).then(() => {
  console.log('then1');
  console.log('推1-1入队');
  new Promise(resolve => {
    resolve();
  }).then(() => {
    console.log('then1-1');
    console.log('推1-2入队');
  }).then(() => {
    console.log('then1-2')
  });
  console.log('推2入队');
}).then(() => {
  console.log('then2');
  console.log('推2-1入队');
  new Promise(resolve => {
    resolve();
  }).then(() => {
    console.log('then2-1');
    console.log('推2-1-1入队');
    new Promise((resolve) => {
      resolve();
    }).then(() => {
      console.log('then2-1-1');
      console.log('推2-1-2入队');
    }).then(() => {
      console.log('then2-1-2')
    });
    console.log('推2-2入队');
  }).then(() => {
    console.log('then2-2');
    console.log('推2-3入队');
  }).then(() => {
    console.log('then2-3');
  });
  console.log('推3入队');
}).then(() => {
  console.log('then3');
  console.log('推3-1入队');
  new Promise(res => {
    res();
  }).then(() => {
    console.log('then3-1');
    console.log('推3-2入队');
  }).then(() => {
    console.log('then3-2');
  });
});

// then1
// 推1-1入队
// 推2入队
// then1-1
// 推1-2入队
// then2
// 推2-1入队
// 推3入队
// then1-2
// then2-1
// 推2-1-1入队
// 推2-2入队
// then3
// 推3-1入队
// then2-1-1
// 推2-1-2入队
// then2-2
// 推2-3入队
// then3-1
// 推3-2入队
// then2-1-2
// then2-3
// then3-2

复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享