interview
frontend-classic
JS如何顺序执行10个异步任务?

前端经典面试题合集, JS 如何顺序执行 10 个异步任务?

前端经典面试题合集, JS 如何顺序执行 10 个异步任务?

QA

Step 1

Q:: JS 如何顺序执行 10 个异步任务?

A:: 为了顺序执行10个异步任务,我们可以使用 async/await 来实现。示例代码如下:

 
async function executeTasks(tasks) {
  for (let task of tasks) {
    await task();
  }
}
 
const tasks = [
  () => new Promise(resolve => setTimeout(() => resolve('Task 1'), 1000)),
  () => new Promise(resolve => setTimeout(() => resolve('Task 2'), 1000)),
  // ... 8 more tasks
];
 
executeTasks(tasks).then(() => console.log('All tasks completed.'));
 

这种方法确保了每个任务在前一个任务完成后才开始执行。

Step 2

Q:: Promise.all 和 Promise.race 的区别是什么?

A:: Promise.all 用于并行执行多个 Promise 并在所有 Promise 都完成后执行一个回调。Promise.race 用于并行执行多个 Promise 并在第一个 Promise 完成后执行一个回调。示例代码:

 
// Promise.all 示例
Promise.all([promise1, promise2]).then(results => {
  console.log('All promises completed', results);
});
 
// Promise.race 示例
Promise.race([promise1, promise2]).then(result => {
  console.log('First promise completed', result);
});
 

Promise.all 适用于需要等待所有任务都完成的场景,Promise.race 适用于只关心最快完成任务的场景。

Step 3

Q:: 什么是事件循环 (Event Loop)

A:: 事件循环是 JavaScript 处理异步操作的机制。它的工作原理包括以下步骤: 1. 所有同步任务都在主线程上执行,形成一个执行栈 (Call Stack)2. 主线程之外,有一个任务队列 (Task Queue)。只要异步任务有了运行结果,就在任务队列之中放置一个事件。 3. 一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列中的事件,将可执行的异步任务添加到执行栈中继续执行。

事件循环确保了 JavaScript 代码的非阻塞执行,使其能够处理大量的异步操作而不会卡死。

Step 4

Q:: 什么是回调地狱 (Callback Hell)?如何避免?

A:: 回调地狱是指当我们在处理多层嵌套的异步回调时,代码变得难以阅读和维护。避免回调地狱的方法包括: 1. 使用 Promises 来处理异步操作。 2. 使用 async/await 语法。 3. 将回调函数拆分成多个单独的函数。

示例代码:

 
// 使用 Promises
asyncFunction1()
  .then(result1 => asyncFunction2(result1))
  .then(result2 => asyncFunction3(result2))
  .catch(error => console.error(error));
 
// 使用 async/await
async function executeTasks() {
  try {
    const result1 = await asyncFunction1();
    const result2 = await asyncFunction2(result1);
    const result3 = await asyncFunction3(result2);
  } catch (error) {
    console.error(error);
  }
}
 

用途

这些内容主要是为了考察候选人对 JavaScript 异步编程的理解和实际操作能力。在实际生产环境中,处理异步任务是非常常见的需求,比如发送网络请求、读取文件、定时任务等。如果开发者不了解这些概念,可能会导致程序运行不稳定、性能低下,甚至出现意料之外的错误。\n

相关问题

🦆
什么是 Promise?如何使用它?

Promise 是一种用于处理异步操作的对象。它代表了一个异步操作的最终完成(或失败)及其结果值。使用 Promise 的示例代码:

 
let promise = new Promise((resolve, reject) => {
  // 异步操作
  setTimeout(() => resolve('成功'), 1000);
});
 
promise.then(result => console.log(result)).catch(error => console.error(error));
 
🦆
什么是 asyncawait?如何使用?

async/await 是 JavaScript 用于处理异步操作的语法糖,使代码更清晰、更易于理解。async 函数返回一个 Promise,await 关键字可以暂停 async 函数的执行,等待 Promise 完成。示例代码:

 
async function fetchData() {
  try {
    let response = await fetch('https://api.example.com/data');
    let data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Error fetching data:', error);
  }
}
fetchData();
 
🦆
JavaScript 中的事件驱动编程是什么?

事件驱动编程是一种编程范式,其中程序的流程是由事件触发的。JavaScript 中,事件驱动编程广泛应用于处理用户交互(如点击、输入等)和异步操作(如网络请求、定时任务等)。事件监听器(event listener)和回调函数(callback)是实现事件驱动编程的关键。示例代码:

 
document.getElementById('button').addEventListener('click', () => {
  console.log('Button clicked');
});
 
🦆
什么是微任务 Microtasks 和宏任务 Macrotasks?

微任务和宏任务是 JavaScript 事件循环中的两个任务队列。微任务包括 Promise 的回调函数、MutationObserver 等,宏任务包括 setTimeout、setInterval、I/O 操作等。事件循环首先执行所有的微任务,然后再执行一个宏任务,如此循环往复。

示例代码:

 
console.log('script start');
 
setTimeout(() => {
  console.log('setTimeout');
}, 0);
 
Promise.resolve().then(() => {
  console.log('promise1');
}).then(() => {
  console.log('promise2');
});
 
console.log('script end');
// 输出顺序:script start, script end, promise1, promise2, setTimeout