乐趣区

关于javascript:异步编程面试题解析

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 start

setTimeout(function () {console.log("setTimeout");
  // 17、控制台输入 setTimeout
}, 0);
// 4、设置一个定时器(增加宏工作 1)async1();
// 5、执行 async1

new Promise(function (resolve) {console.log("promise1");
  // 11、控制台打印 promise1
  resolve();
  // 12、增加微工作 2
}).then(function () {console.log("promise2");
  // 16、执行微工作 2 控制台打印 promise2
});
// 10、立刻执行 new Promise

console.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、输入 1

setTimeout((_) => {console.log(2);
  // 22、输入 2
}, 1000);
// 2、增加 宏工作 1

async function fn() {console.log(3);
  // 8、输入 3
  setTimeout((_) => {console.log(4);
    // 输入 4
  }, 20);
  // 9、增加一个 宏工作 2
  return Promise.reject();}
// 3、初始化函数 fn
async function run() {console.log(5);
  // 6、输入 5
  await fn();
  // 7、执行 fn
  // 8、增加一个 微工作 1
  console.log(6);
  // 13、下面返回的失败状态,所以下面代码不执行
}
// 4、初始化函数 run
run();
// 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、增加一个 宏工作 3
console.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 返回胜利态才会执行(然而此时不等,列为工作队列中的微工作),若返回失败状态,前面的代码不执行。
退出移动版