異步編程面試題解析

異步編程面試題解析.png

一、字節跳動面試題

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");

解析:javascript

async function async1() {
  console.log("async1 start");
  // 六、控制檯打印 async1 start
  await async2();
  // 七、先執行 async2
  // 八、下面的代碼須要等待返回正確的 Promise 後才執行(異步|微任務)(添加微任務1)
  console.log("async1 end");
  // 1五、執行微任務1 控制檯打印 async1 end
}
// 一、建立一個 async1 函數

async function async2() {
  console.log("async2");
  // 九、控制檯打印 async2
}
// 二、建立一個 async2 函數

console.log("script start");
// 三、控制檯打印 script start

setTimeout(function () {
  console.log("setTimeout");
  // 1七、控制檯輸出 setTimeout
}, 0);
// 四、設置一個定時器 (添加宏任務1)

async1();
// 五、執行 async1

new Promise(function (resolve) {
  console.log("promise1");
  // 十一、控制檯打印 promise1
  resolve();
  // 十二、添加微任務2
}).then(function () {
  console.log("promise2");
  // 1六、執行微任務2 控制檯打印 promise2
});
// 十、當即執行 new Promise

console.log("script end");
// 1三、控制檯打印 script end
// 1四、清空微任務
// 1五、執行一個宏任務

// script start
// async1 start
// async2
// promise1
// script end
// async1 end
// promise2
// setTimeout

總結:java

  • 微任務包括 process.nextTickpromiseMutationObserver,其中 process.nextTick 爲 Node 獨有。
  • 宏任務包括 scriptsetTimeoutsetIntervalsetImmediateI/OUI rendering

這裏不少人會有個誤區,認爲微任務快於宏任務,實際上是錯誤的。由於宏任務中包括了 script ,瀏覽器會先執行一個宏任務,接下來有異步代碼的話纔會先執行微任務。面試

二、涉及到 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

setTimeout((_) => {
  console.log(2);
  // 2二、輸出 2
}, 1000);
// 二、添加 宏任務1

async function fn() {
  console.log(3);
  // 八、輸出 3
  setTimeout((_) => {
    console.log(4);
    // 輸出 4
  }, 20);
  // 九、添加一個 宏任務2
  return Promise.reject();
}
// 三、初始化函數fn
async function run() {
  console.log(5);
  // 六、輸出 5
  await fn();
  // 七、執行fn
  // 八、添加一個 微任務1
  console.log(6);
  // 1三、上面返回的失敗狀態,因此上面代碼不執行
}
// 四、初始化函數 run
run();
// 五、執行run函數

// 須要執行150MS左右
for (let i = 0; i < 90000000; i++) {}
// 九、執行循環 150ms (以前設置的定時器到時候,可是要繼續把同步任務執行完)

setTimeout((_) => {
  console.log(7);
  // 1六、輸出 7
  new Promise((resolve) => {
    console.log(8);
    // 1七、執行promise 輸出 8
    // 1八、添加一個微任務2
    resolve();
  }).then((_) => {
    console.log(9);
    // 20、輸出 9
  });
}, 0);
// 十、添加一個 宏任務3
console.log(10);
// 十一、輸出 10
// 十二、執行一隊微任務  執行微任務1
// 1四、執行一個宏任務  找到最須要執行的宏任務(定時器到時) 執行宏任務2
// 1五、沒有微任務 再執行一個宏任務(定時器到時) 執行宏任務3
// 1九、執行一隊微任務 執行微任務2
// 2一、執行一個宏任務(等待定時器到時執行) 執行宏任務1

// 1
// 5
// 3
// 10
// 4
// 7
// 8
// 9
// 2

總結:promise

  • await fun(); 當前這一行代碼當即執行,而它的異步是下面的代碼須要fn返回成功態纔會執行(可是此時不等,列爲任務隊列中的微任務),若返回失敗狀態,後面的代碼不執行。
相關文章
相關標籤/搜索