能否用yield调用非异步方法?Generator函数同步调用报错问题
问题解答:Generator调用非异步方法时报错"Generator is already running"
咱们先拆解你遇到的错误根源,再给出对应的解决思路和代码调整方案。
错误原因
你碰到的Uncaught (in promise) TypeError: Generator is already running,核心问题是重复嵌套调用了生成器的next()方法,违反了生成器的执行规则:生成器同一时间只能处于「暂停」或「执行」其中一种状态,不能在它执行过程中再次触发next()。
具体看你的代码逻辑:
- 第一个
yield doSomethingAsync()执行后,生成器进入暂停状态,等待axios请求完成。 - 请求结束后,
doSomethingAsync的then回调调用generatorInstance.next(response.data),生成器从暂停恢复,执行第一个console.log,紧接着走到第二个yield doSomethingNonAsync()。 - 但
doSomethingNonAsync内部直接调用了generatorInstance.next("foo")——这时候生成器还处于正在执行的状态(刚从第一个next恢复,还没走完当前执行流程),再次调用next()就触发了这个错误。
解决办法
核心思路是:仅当生成器处于暂停状态时,才能调用next()。对于非异步方法,不需要手动调用next(),让yield自动接收方法的返回值即可。
调整后的代码示例
生成器函数
function* generatorFunction () { var asyncResult = yield doSomethingAsync(); console.log(asyncResult) // 非异步方法直接返回值,yield会自动把值传递给nonAsyncResult var nonAsyncResult = yield doSomethingNonAsync(); console.log(nonAsyncResult) }
辅助方法
// 异步方法:返回Promise,由生成器执行器处理后续的next调用 function doSomethingAsync() { return axios.get("https://jsonplaceholder.typicode.com/posts") .then(response => response.data); } // 非异步方法:直接返回值,不需要手动调用next function doSomethingNonAsync(){ return "foo"; }
生成器自动执行器
需要一个简单的执行器来驱动生成器,自动处理异步和同步的yield结果:
const generatorInstance = generatorFunction(); function run(gen) { const { value, done } = gen.next(); if (done) return; // 如果yield出来的是Promise(异步操作),等待完成后继续驱动生成器 if (value instanceof Promise) { value.then(data => { gen.next(data); run(gen); }); } else { // 同步值直接传递,继续执行 gen.next(value); run(gen); } } run(generatorInstance);
更简洁的替代方案:使用async/await
其实async/await本质就是生成器+自动执行器的语法糖,写起来更简洁直观,完全可以替代你当前的写法:
async function asyncFunction() { const asyncResult = await axios.get("https://jsonplaceholder.typicode.com/posts").then(res => res.data); console.log(asyncResult); const nonAsyncResult = doSomethingNonAsync(); console.log(nonAsyncResult); } function doSomethingNonAsync(){ return "foo"; } asyncFunction();
内容的提问来源于stack exchange,提问作者stackoverfloweth
相关产品推荐
相关产品推荐

