Search code examples
javascriptiterable

How to make iterable class method?


It's telling me "TypeError: Foo.my_method(...) is not a function or its return value is not async iterable". How to make it so?

class Foo {
  constructor() {
        return (async () => { this.sleep(1000) })()
  }
  
  async *my_method(message) {
    let pos = 0
    while (true) {
      yield message.charAt(pos)
      await this.sleep(100)
      pos += 1
    }
  }
  
  sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
}

let foo = new Foo().then(async () => {
    for await (let msg of foo.my_method("AAAA")) {
        msgs.push(msg)
    }
})

Solution

  • Doing

    let foo = new Foo().then(
    

    will set foo to be a Promise, which is why you couldn't do foo.my_method()

    I think what you are trying to do is this:

    class Foo {
      load(){
        return Promise.resolve()
      }
      
      async *my_method(message) {
        let pos = 0
        while (pos < message.length) {
          yield await this.sleep(100).then(() => message.charAt(pos))
          pos += 1
        }
      }
      
      sleep(ms) {
            return new Promise(resolve => setTimeout(resolve, ms));
        }
    }
    
    (async function(){
      let foo = new Foo()
      await foo.load()
      
      const msg = []
      for await (const data of foo.my_method("ABCD")) {
          msg.push(data)
      }
      console.log(msg)
    })()

    I have just added a condition on the while so that your generator terminates at some point, and I put the async loop into an (async) IFEE, so that the generator can be awaited directly (it looks like this is what you were trying to do).

    Does that work for you? Let me know if it make sense.