1、字节跳动面试题

async function async1() {  console.log("async1 start");  await async2();  console.log("async1 end");}async function async2() {  console.log("async2");}console.log("script start");setTimeout(function () {  console.log("setTimeout");}, 0);async1();new Promise(function (resolve) {  console.log("promise1");  resolve();}).then(function () {  console.log("promise2");});console.log("script end");

解析:

async function async1() {  console.log("async1 start");  // 6、控制台打印 async1 start  await async2();  // 7、先执行 async2  // 8、上面的代码须要期待返回正确的 Promise 后才执行(异步|微工作)(增加微工作1)  console.log("async1 end");  // 15、执行微工作1 控制台打印 async1 end}// 1、创立一个 async1 函数async function async2() {  console.log("async2");  // 9、控制台打印 async2}// 2、创立一个 async2 函数console.log("script start");// 3、控制台打印 script startsetTimeout(function () {  console.log("setTimeout");  // 17、控制台输入 setTimeout}, 0);// 4、设置一个定时器 (增加宏工作1)async1();// 5、执行 async1new Promise(function (resolve) {  console.log("promise1");  // 11、控制台打印 promise1  resolve();  // 12、增加微工作2}).then(function () {  console.log("promise2");  // 16、执行微工作2 控制台打印 promise2});// 10、立刻执行 new Promiseconsole.log("script end");// 13、控制台打印 script end// 14、清空微工作// 15、执行一个宏工作// script start// async1 start// async2// promise1// script end// async1 end// promise2// setTimeout

总结:

  • 微工作包含 process.nextTickpromiseMutationObserver,其中 process.nextTick 为 Node 独有。
  • 宏工作包含 scriptsetTimeoutsetIntervalsetImmediateI/OUI rendering

这里很多人会有个误区,认为微工作快于宏工作,其实是谬误的。因为宏工作中包含了 script ,浏览器会先执行一个宏工作,接下来有异步代码的话才会先执行微工作。

2、波及到 for 循环异步编程题

console.log(1);setTimeout((_) => {  console.log(2);}, 1000);async function fn() {  console.log(3);  setTimeout((_) => {    console.log(4);  }, 20);  return Promise.reject();}async function run() {  console.log(5);  await fn();  console.log(6);}run();// 须要执行150MS左右for (let i = 0; i < 90000000; i++) {}setTimeout((_) => {  console.log(7);  new Promise((resolve) => {    console.log(8);    resolve();  }).then((_) => {    console.log(9);  });}, 0);console.log(10);

解析

console.log(1);// 1、输入 1setTimeout((_) => {  console.log(2);  // 22、输入 2}, 1000);// 2、增加 宏工作1async function fn() {  console.log(3);  // 8、输入 3  setTimeout((_) => {    console.log(4);    // 输入 4  }, 20);  // 9、增加一个 宏工作2  return Promise.reject();}// 3、初始化函数fnasync function run() {  console.log(5);  // 6、输入 5  await fn();  // 7、执行fn  // 8、增加一个 微工作1  console.log(6);  // 13、下面返回的失败状态,所以下面代码不执行}// 4、初始化函数 runrun();// 5、执行run函数// 须要执行150MS左右for (let i = 0; i < 90000000; i++) {}// 9、执行循环 150ms (之前设置的定时器到时候,然而要持续把同步工作执行完)setTimeout((_) => {  console.log(7);  // 16、输入 7  new Promise((resolve) => {    console.log(8);    // 17、执行promise 输入 8    // 18、增加一个微工作2    resolve();  }).then((_) => {    console.log(9);    // 20、输入 9  });}, 0);// 10、增加一个 宏工作3console.log(10);// 11、输入 10// 12、执行一队微工作  执行微工作1// 14、执行一个宏工作  找到最须要执行的宏工作(定时器到时) 执行宏工作2// 15、没有微工作 再执行一个宏工作(定时器到时) 执行宏工作3// 19、执行一队微工作 执行微工作2// 21、执行一个宏工作(期待定时器到时执行) 执行宏工作1// 1// 5// 3// 10// 4// 7// 8// 9// 2

总结:

  • await fun(); 以后这一行代码立刻执行,而它的异步是上面的代码须要fn返回胜利态才会执行(然而此时不等,列为工作队列中的微工作),若返回失败状态,前面的代码不执行。