代码示例
function* asyncTasks() {
try {
// 模拟第一个异步任务(这里用setTimeout模拟网络请求)
const result1 = yield new Promise((resolve) => {
setTimeout(() => {
resolve('第一个任务结果');
}, 1000);
});
console.log('第一个任务结果:', result1);
// 模拟第二个异步任务,依赖第一个任务的结果
const result2 = yield new Promise((resolve) => {
setTimeout(() => {
resolve('第二个任务结果,依赖 ' + result1);
}, 1000);
});
console.log('第二个任务结果:', result2);
// 模拟第三个异步任务,依赖第二个任务的结果
const result3 = yield new Promise((resolve) => {
setTimeout(() => {
resolve('第三个任务结果,依赖 ' + result2);
}, 1000);
});
console.log('第三个任务结果:', result3);
} catch (error) {
console.error('任务执行出错:', error);
}
}
function runGenerator(generator) {
const gen = generator();
function step(result) {
let { value, done } = result;
if (done) return;
if (value && typeof value.then === 'function') {
value.then((data) => {
step(gen.next(data));
}).catch((error) => {
gen.throw(error);
});
} else {
step(gen.next(value));
}
}
step(gen.next());
}
runGenerator(asyncTasks);
原理解释
- 生成器函数定义:
asyncTasks
是一个生成器函数,使用 function*
关键字定义。在生成器函数内部,通过 yield
关键字暂停函数执行,并返回一个值(这里返回的是 Promise
对象)。
- 异步任务模拟:使用
setTimeout
模拟网络请求,实际应用中可以替换为真实的网络请求库(如 fetch
)。每次 yield
返回一个 Promise
,当这个 Promise
被解决(resolved)时,yield
表达式的值就是 Promise
的解决值。
- 生成器状态管理与执行:
runGenerator
函数用于执行生成器。它首先通过 generator()
创建一个生成器实例 gen
。step
函数负责驱动生成器的执行,每次调用 gen.next()
来恢复生成器执行,并将 Promise
的解决值作为参数传递给 next
。如果 yield
返回的是一个 Promise
,则等待 Promise
解决后再继续执行下一步;如果 yield
返回的不是 Promise
,则直接进入下一步。
- 错误处理:在生成器函数内部使用
try - catch
块捕获可能出现的错误,当 Promise
被拒绝(rejected)时,通过 gen.throw(error)
将错误传递到生成器内部的 catch
块进行处理。这样就实现了通过生成器及其状态管理来优雅地控制一系列有依赖关系的异步任务。