Generator函数通过yield暂停执行并交出控制权,外部执行器用next()恢复执行并将结果传回,从而将异步流程线性化。其优势在于避免回调地狱、实现清晰的同步式代码结构、支持try...catch统一错误处理,并可通过执行器自动推进。相比async/await,Generator更灵活,支持双向通信、手动控制迭代及自定义任务调度,适用于需精细控制的复杂场景。

Generator函数通过其独特的
yield
next()
要用Generator函数实现复杂的异步流程控制,核心在于理解
yield
next()
一个典型的模式是,我们定义一个Generator函数,在其中使用
yield
yield
next()
例如,我们有一个模拟异步请求的函数:
function fakeFetch(url) {
return new Promise(resolve => {
setTimeout(() => {
console.log(`Fetched data from ${url}`);
resolve({ url, data: `Some data for ${url}` });
}, Math.random() * 1000 + 500);
});
}
// 我们的异步流程Generator
function* asyncFlow() {
console.log('Step 1: Start fetching data1');
const result1 = yield fakeFetch('https://api.example.com/data1');
console.log('Step 2: Data1 received:', result1.data);
console.log('Step 3: Start fetching data2 based on data1');
const result2 = yield fakeFetch(`https://api.example.com/data2?id=${result1.data.split(' ')[2]}`);
console.log('Step 4: Data2 received:', result2.data);
console.log('Step 5: Process both results');
return `Final result: ${result1.data} and ${result2.data}`;
}然后,我们需要一个执行器来驱动这个
asyncFlow
function run(generator) {
const it = generator(); // 获取迭代器
function go(result) {
if (result.done) return result.value; // Generator执行完毕,返回最终值
return Promise.resolve(result.value).then(
value => go(it.next(value)), // 异步操作成功,将结果传回Generator
error => go(it.throw(error)) // 异步操作失败,将错误抛回Generator
);
}
return go(it.next()); // 启动Generator
}
// 运行我们的异步流程
run(asyncFlow).then(finalResult => {
console.log('All done! Final output:', finalResult);
}).catch(error => {
console.error('Flow error:', error);
});通过这种方式,原本需要层层嵌套回调或Promise
.then()
说实话,我个人觉得Generator函数最直观、最让人眼前一亮的优势,就是它能彻底终结“回调地狱”那种让人头疼的局面。想想看,在Promise普及之前,处理多个相互依赖的异步操作,代码很快就会变成一个深度嵌套的金字塔,每一层都是一个回调函数,参数传递和错误处理简直是噩梦。
举个例子,假设我们要依次执行三个异步操作,每个操作都依赖前一个的结果:
// 回调地狱版
asyncOperation1(param1, function(err1, res1) {
if (err1) { /* handle error */ return; }
asyncOperation2(res1.id, function(err2, res2) {
if (err2) { /* handle error */ return; }
asyncOperation3(res2.token, function(err3, res3) {
if (err3) { /* handle error */ return; }
console.log('All done:', res3);
});
});
});这种代码,别说维护了,光是看一眼都觉得眼睛疼。参数层层传递,错误处理也变得重复且易错。
而用Generator函数,结合上面提到的执行器,这段逻辑会变得异常清晰:
function* sequentialAsyncFlow() {
try {
const res1 = yield asyncOperation1(param1);
const res2 = yield asyncOperation2(res1.id);
const res3 = yield asyncOperation3(res2.token);
console.log('All done:', res3);
} catch (error) {
console.error('An error occurred:', error);
}
}
// 假设 asyncOperationX 返回 Promise
// run(sequentialAsyncFlow);你看,代码的执行流程变得一目了然,就像我们写同步代码一样,从上到下,一步一步。
yield
try...catch
构建一个简易的Generator执行器,其实就是实现一个能自动调用
next()
yield
function co(generatorFn) {
return new Promise((resolve, reject) => {
const gen = generatorFn(); // 获取Generator的迭代器
function step(nextFn) {
let generatorResult;
try {
generatorResult = nextFn(); // 调用next()或throw()
} catch (err) {
return reject(err); // Generator内部抛出错误
}
const { value, done } = generatorResult;
if (done) {
return resolve(value); // Generator执行完毕
}
// 确保yield的值是一个Promise,如果不是,也包装成Promise
Promise.resolve(value).then(
res => {
step(() => gen.next(res)); // Promise成功,将结果传回Generator
},
err => {
step(() => gen.throw(err)); // Promise失败,将错误抛回Generator
}
);
}
step(() => gen.next(undefined)); // 启动Generator,第一次next()不带参数
});
}
// 结合上面的asyncFlow Generator
// co(asyncFlow).then(finalResult => {
// console.log('Co-runner finished:', finalResult);
// }).catch(error => {
// console.error('Co-runner error:', error);
// });这个
co
gen
step
nextFn()
gen.next(value)
gen.throw(error)
nextFn()
reject
generatorResult.done
true
generatorResult.value
resolve
done
false
yield
Promise.resolve()
step
gen.next(res)
step
gen.throw(err)
try...catch
step(() => gen.next(undefined))
next()
yield
这个执行器虽然简陋,但它完整地展现了Generator函数如何与外部环境协作,实现异步流程的自动化控制。理解了它,你就能明白像Koa 1.x或一些早期Node.js库是如何利用Generator来构建强大的中间件系统的。
毫无疑问,
async/await
async/await
async/await
Generator的独特价值,主要体现在它更强的控制力和更广泛的适用性上:
async/await
await
await
yield
yield
yield
async/await
next()
yield
next()
next()
next()
yield
yield
async/await
yield
next(answer)
虽然在日常的异步请求处理中,
async/await
以上就是如何用Generator函数实现复杂的异步流程控制?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号