You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现可迭代的类方法?解决「TypeError: Foo.my_method(...) is not a function or its return value is not async iterable」报错问题

如何实现可迭代的类方法?解决「TypeError: Foo.my_method(...) is not a function or its return value is not async iterable」报错问题

嘿,我来帮你揪出这个报错的根源,其实问题出在构造函数的返回值上!

你看,你的Foo构造函数里返回了一个异步函数的Promise:

constructor() {
  return (async () => { this.sleep(1000) })()
}

这就导致new Foo()得到的不是Foo类的实例,而是一个Promise对象!后面你写的let foo = new Foo().then(...),这里的foo其实是then方法返回的Promise,不是真正的Foo实例——Promise对象当然没有my_method这个方法,所以才会抛出那个错误。

另外还有两个小细节要调整:一是构造函数里的this.sleep(1000)没加await,等于白执行;二是my_method里的while(true)会无限循环,最好加个终止条件(比如遍历完message的所有字符)。

下面给你两种可行的修正方案:

方案一:用静态异步工厂方法创建实例(推荐)

把异步初始化逻辑放到静态方法里,构造函数保持默认返回实例:

class Foo {
  constructor() {
    // 构造函数不做异步操作,返回默认的类实例
  }

  // 静态工厂方法,负责异步初始化并返回实例
  static async create() {
    const fooInstance = new Foo();
    await fooInstance.sleep(1000); // 等待初始化的sleep完成
    return fooInstance;
  }

  async *my_method(message) {
    let pos = 0;
    // 加终止条件,避免无限循环
    while (pos < message.length) {
      yield message.charAt(pos);
      await this.sleep(100);
      pos += 1;
    }
  }

  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

// 使用方式
(async () => {
  const foo = await Foo.create();
  const msgs = [];
  for await (let msg of foo.my_method("AAAA")) {
    msgs.push(msg);
    console.log(msg); // 会每隔100ms输出一个"A"
  }
  console.log(msgs); // 最终输出 ['A','A','A','A']
})();

方案二:用实例的init方法处理异步初始化

如果不想用静态方法,可以给实例加一个initializedPromise,确保异步初始化完成后再执行方法:

class Foo {
  constructor() {
    // 把异步初始化逻辑放到init方法,并用initialized保存Promise
    this.initialized = this.init();
  }

  async init() {
    await this.sleep(1000); // 等待初始化完成
  }

  async *my_method(message) {
    // 先等待初始化完成,再执行生成器逻辑
    await this.initialized;
    let pos = 0;
    while (pos < message.length) {
      yield message.charAt(pos);
      await this.sleep(100);
      pos += 1;
    }
  }

  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

// 使用方式
(async () => {
  const foo = new Foo();
  const msgs = [];
  for await (let msg of foo.my_method("AAAA")) {
    msgs.push(msg);
    console.log(msg);
  }
  console.log(msgs);
})();

核心知识点总结

  • 构造函数不要返回Promise(或其他非实例对象),否则new Class()的结果就不是类实例了
  • 你写的async *my_method本身就是合法的异步生成器,只要调用它的是正确的Foo实例,就会是async iterable,符合for await...of的要求
  • 类的异步初始化逻辑,尽量放到静态工厂方法或单独的init方法中,不要在构造函数里搞异步返回

备注:内容来源于stack exchange,提问作者rigiva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 10:59:07