Generator函数通过yield实现暂停-恢复机制,配合next()和Promise可将异步流程分段控制;手动驱动需await每次yield值,自动执行器co可封装此逻辑;结合UI可实现每步状态更新与用户交互。

Generator 函数本身不执行异步操作,但它提供了一种“暂停-恢复”的执行机制,配合 yield 和手动/自动的迭代控制,可以将一个长流程拆成多个可中断、可观察、可干预的逻辑段。关键在于:用 yield 标记分段点,用 next() 触发下一段,把异步操作包装成能返回 Promise 的“可恢复步骤”。
理解 Generator 的暂停本质
Generator 函数调用后返回一个迭代器对象,不会立即执行函数体,只有调用 next() 才运行到下一个 yield 表达式并暂停。每次 next() 返回 { value, done },其中 value 就是 yield 后面的值——这个值可以是 Promise、配置对象、甚至另一个 Generator。
例如:
function* fetchFlow() {yield fetch('/api/user');
yield fetch('/api/posts');
return 'done';
}
手动控制:用 next() 驱动每一步并等待 Promise
由于 yield 返回的是 Promise,你需要在每次 next() 后显式 await 它的 value,再调用下一次 next()。这样就把异步链“展开”成了可控的步进过程。
立即学习“前端免费学习笔记(深入)”;
典型写法:
const gen = fetchFlow();
let result = gen.next();
while (!result.done) {
const res = await result.value; // 等待当前 yield 的 Promise
console.log('完成一步:', res);
result = gen.next(res); // 把上一步结果传给下一步(可选)
}
return result.value;
}
封装成自动执行器(类似 co 库的简化版)
重复写 while + await + next 很繁琐,可以封装一个通用执行器,自动处理 Promise 类型的 yield 值,并支持传参、错误捕获和非 Promise 值透传。
简易实现:
function co(genFn, ...args) {const gen = genFn(...args);
function next(data) {
const { value, done } = gen.next(data);
if (done) return Promise.resolve(value);
if (value instanceof Promise) {
return value.then(res => next(res)).catch(err => gen.throw(err));
}
return next(value); // 非 Promise 直接继续
}
return next();
}
使用:
co(function* () {<br> const user = yield fetch('/user').then(r => r.json());<br> console.log('用户加载完成');<br> const posts = yield fetch(`/posts?uid=${user.id}`).then(r => r.json());<br> return { user, posts };<br>});
结合 UI 控制:每步完成后更新状态或等待用户确认
Generator 的真正优势在于“可控暂停”。你可以在每步 yield 后插入 UI 交互,比如显示加载状态、弹出确认框、或根据用户选择跳过某步。
示例:带手动确认的表单提交流程
function* formSubmitFlow() {yield { type: 'show', message: '正在校验表单...' };
const valid = yield validateForm();
if (!valid) yield { type: 'error', message: '校验失败' };
yield { type: 'show', message: '提交中...' };
const res = yield submitToServer();
yield { type: 'success', data: res };
}
UI 层监听每一步的 value(这里是个普通对象),决定渲染什么、是否调用 next()、或调用 gen.throw() 中断流程。


















