代码实现
function readFileAsync(filePath) {
return new Promise((resolve, reject) => {
// 模拟异步读取文件操作
setTimeout(() => {
resolve(`File content of ${filePath}`);
}, 1000);
});
}
function* asyncTasks() {
const file1Content = yield readFileAsync('file1.txt');
console.log(file1Content);
const file2Content = yield readFileAsync('file2.txt');
console.log(file2Content);
const file3Content = yield readFileAsync('file3.txt');
console.log(file3Content);
}
const taskGenerator = asyncTasks();
let task = taskGenerator.next();
while (!task.done) {
task.value.then(result => {
task = taskGenerator.next(result);
}).catch(error => {
console.error(error);
task = taskGenerator.throw(error);
});
}
原理解释
- 生成器(Generator):生成器是一种特殊的函数,它可以暂停和恢复执行。通过
function*
关键字定义,使用yield
关键字暂停函数执行并返回一个值。当生成器函数被调用时,它不会立即执行,而是返回一个生成器对象。
- yield关键字:在生成器函数内部,
yield
用于暂停函数的执行,并返回其后跟随的表达式的值。它可以看作是一个“返回点”,下次调用next()
方法时,生成器会从暂停的yield
处继续执行。
- 异步任务控制:在上述代码中,
asyncTasks
是一个生成器函数,它包含多个异步任务(通过readFileAsync
模拟)。每个yield
后面跟一个Promise对象(代表异步操作)。生成器开始执行时,遇到第一个yield
暂停,返回readFileAsync('file1.txt')
这个Promise对象。
- 执行流程:
- 首先创建生成器对象
taskGenerator
并调用next()
方法启动生成器,此时它暂停在第一个yield
处,返回第一个异步任务(Promise)。
- 使用
.then()
处理Promise的解析结果,当Promise被解析(即文件读取完成),将结果作为参数传递给next()
方法,生成器从暂停处继续执行,将解析结果赋值给file1Content
,并打印内容。然后遇到下一个yield
再次暂停,返回第二个异步任务。
- 重复上述过程,直到所有异步任务完成,生成器的
done
属性变为true
,循环结束。
- 异常处理:如果Promise被拒绝(即异步操作出错),通过
.catch()
捕获错误,并使用throw(error)
将错误传递给生成器,生成器会在暂停处抛出该错误,可以在生成器内部进行相应处理。