MST

星途 面试题库

面试题:JavaScript 生成器在异步编程中的应用

在 JavaScript 异步编程场景下,阐述生成器相较于传统回调函数和 Promise 的优势。请通过代码示例展示如何利用生成器函数和迭代器来实现异步任务的顺序执行,并且处理可能出现的错误。
34.8万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

生成器相较于传统回调函数和 Promise 的优势

  1. 代码可读性更高:回调函数容易出现回调地狱,多层嵌套使得代码逻辑复杂且难以维护。Promise 通过链式调用解决了回调地狱问题,但生成器使用更接近同步代码的方式来编写异步代码,提升了可读性。
  2. 更细粒度的控制:生成器可以暂停和恢复执行,开发人员能够更精确地控制异步操作的流程,而 Promise 一旦开始就无法暂停。
  3. 错误处理更直观:在生成器中,错误处理可以像同步代码一样使用 try - catch 块,相比 Promise 的链式调用中通过 .catch() 捕获错误,更符合常规的编程习惯。

代码示例

function asyncTask1() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Task 1 completed');
        }, 1000);
    });
}

function asyncTask2() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Task 2 completed');
        }, 1500);
    });
}

function asyncTask3() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(new Error('Task 3 failed'));
        }, 2000);
    });
}

function* asyncTasks() {
    try {
        const result1 = yield asyncTask1();
        console.log(result1);
        const result2 = yield asyncTask2();
        console.log(result2);
        const result3 = yield asyncTask3();
        console.log(result3);
    } catch (error) {
        console.error('Error:', error.message);
    }
}

const taskIterator = asyncTasks();
function runTask() {
    const task = taskIterator.next();
    if (!task.done) {
        task.value.then(data => {
            taskIterator.next(data);
            runTask();
        }).catch(error => {
            taskIterator.throw(error);
        });
    }
}
runTask();

在上述代码中:

  1. asyncTask1asyncTask2asyncTask3 是模拟的异步任务,返回 Promise。
  2. asyncTasks 是一个生成器函数,使用 yield 暂停执行并等待 Promise 解决。
  3. taskIterator 是生成器的迭代器。
  4. runTask 函数通过迭代器的 next 方法来顺序执行异步任务,当 Promise 解决时,将结果传递给下一个 yield,如果 Promise 被拒绝,则通过 throw 方法将错误传递给生成器内部的 try - catch 块进行处理。