ES6 Generator 函数的异步应用主要通过与 Promise 配合使用来实现。这种模式被称为 "thunk" 模式,它允许你编写看起来是同步的异步代码。
特性:
- 暂停执行:当 Generator 函数遇到 yield 表达式时,它会暂停执行,等待 Promise 解决。
- 恢复执行:当 Promise 完成(解决或拒绝)时,Generator 函数恢复执行,并返回 yield 表达式的结果。
- 错误处理:可以对异步操作中的错误进行捕获和处理。
- 链式调用:可以创建一个链式的异步操作,每个操作都在前一个操作完成后开始。
1. 基本的异步 Generator 函数
javascript
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
function* asyncGenerator() {
console.log("Start");
yield delay(1000); // 等待1秒
console.log("After 1 second");
yield delay(1000); // 再等待1秒
console.log("After another second");
return "Done";
}
let gen = asyncGenerator();
function runGenerator(g) {
let result = g.next();
result.value.then(() => {
if (!result.done) {
runGenerator(g);
}
});
}
runGenerator(gen);
2. 使用 for...of 和 async...await 语法糖
javascript
// 假设我们有以下 async generator
async function* asyncGen() {
yield await Promise.resolve(1);
yield await Promise.resolve(2);
yield await Promise.resolve(3);
}
// 我们可以使用 for...of 循环和 async...await 语法糖来简化调用
(async () => {
for await (let value of asyncGen()) {
console.log(value); // 依次输出 1, 2, 3
}
})();
3. 处理异步操作中的错误
javascript
function* asyncGenWithError() {
try {
yield Promise.reject("Error occurred!");
} catch (e) {
console.log(e); // 输出:Error occurred!
}
}
let genWithError = asyncGenWithError();
genWithError.next().value.catch(err => console.log(err));
4. 使用 yield* 委托给其他异步 Generator 函数
javascript
function* innerAsyncGen() {
yield Promise.resolve("A");
yield Promise.resolve("B");
}
function* outerAsyncGen() {
yield "Start";
yield* innerAsyncGen(); // 委托给另一个异步 Generator 函数
yield "End";
}
let outerGen = outerAsyncGen();
function runOuterGenerator(g) {
let result = g.next();
result.value.then(val => {
if (!result.done) {
runOuterGenerator(g);
}
});
}
runOuterGenerator(outerGen);