简体   繁体   中英

JS: how to use generator and yield in a callback

I use JS generator to yield a value in a callback of setTimeout :

function* sleep() {
  // Using yield here is OK
  // yield 5; 
  setTimeout(function() {
    // Using yield here will throw error
    yield 5;
  }, 5000);
}

// sync
const sleepTime = sleep().next()

Why I can't yield values inside a callback in the generator?

function* declaration is synchronous. You can yield a new Promise object, chain .then() to .next().value to retrieve resolved Promise value

function* sleep() {
  yield new Promise(resolve => {
    setTimeout(() => {
      resolve(5);
    }, 5000);
  })
}

// sync
const sleepTime = sleep().next().value
  .then(n => console.log(n))
  .catch(e => console.error(e));

I came to this question looking for a way to convert a callback that is called every so often (eg a Node stream, event listener, or setInterval callback) into an async iterable, and after some research I found this NPM package that does all that: EventIterator .

EventIterator is a small module that greatly simplifies converting event emitters, event targets, and similar objects into EcmaScript async iterators. It works in browser and Node.js environments.

A basic setInterval iterable:

import { EventIterator } from "event-iterator"
const counter = ms =>
  new EventIterator(({ push }) => {
    let count = 0
    const interval = setInterval(() => push(++count), ms)
    return () => clearInterval(interval)
  })

for await (const count of counter(1000)) console.log(count)

(think of push like yield ).

Though this doesn't technically answer the question, the accepted answer doesn't really answer it either, and this solution seems pretty close to what the OP was looking for.

Extending the answer from the above @BananaAcid and @guest271314

The below code yields in a loop. Thus can yield more than once

async function* foo(loopVal) {
  for(let i=0;i<loopVal;i++){
    yield new Promise(resolve => {
      setTimeout(() => {
        resolve(i);
      }, 5000);
    })
  }
}

(async function() {
  for await (const num of foo(5)) {
    console.log(num);
  }
})();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM