skip to Main Content

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)
    }
})

3

Answers


  1. this.my_method = async funtion(){…}

    Try like this

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
  3. returning async function from the constructor is not ok. in pure js it would do something (not useful at all in the example from the question), but ts just won’t allow that to happen without puting any fo the type.

    I think you are implementing some kind of collection and this is the way to make async iterable collection

    class Foo {
      constructor(private message: string) {}
      async *[Symbol.asyncIterator]() {
        let pos = 0
        while (this.message[pos]) {
          yield this.message.charAt(pos)
          await this.sleep(100)
          pos += 1
        }
      }
      
      sleep(ms: number) {
            return new Promise(resolve => setTimeout(resolve, ms));
        }
    }
    
    async function userCode() {
        let foo = new Foo('xxx');
        const msgs = [];
        for await (let msg of foo) {
            msgs.push(msg)
        }
        console.log(msgs);
    }
    
    

    by declaring Symbol.asyncIterator on the class, all instances would be async iterable

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search