How to setInterval Generator correctly?
Asked Answered
G

5

5

Goal: I want to create a generator function that is being invoked inside setInterval(), and console.log 1 to 10.

the problem: In order to clearInterval() at the end I need a condition to check if gen.next().done === true. but every time the condition runs it actualy calls another .next() so so final print i get is: 1 3 5 7 9 undefined

How do I set a done == true condition without calling .next() ?

function* myGen(){
    let counter = 0;
    for(let i = 0 ; i <= 10; i++){
        yield counter++;    
    }
}

const gen = myGen();
const start = setInterval(() => {
    if(gen.next().done){
        clearInterval(start);
    } else {
        console.log(gen.next().value);  
    }
}, 1500)
Gribble answered 13/1, 2018 at 15:25 Comment(0)
C
11

You remember the object in a variable rather than calling next a second time:

function* myGen(){
    let counter = 0;
    for(let i = 0 ; i <= 10; i++){
        yield counter++;    
    }
}

const gen = myGen();
const start = setInterval(() => {
    var next = gen.next();             // *** Save it here
    if(next.done){                     // *** Use it here...
        clearInterval(start);
    } else {
        console.log(next.value);       // *** ...and here
    }
}, 150)
Cordell answered 13/1, 2018 at 15:28 Comment(0)
M
5

You can alternatively use for..of loop, setTimeout(), async/await to avoid the need to check for .done property value

function* myGen() {
  let counter = 0;
  for (let i = 0; i <= 10; i++) {
    yield counter++;
  }
}

const gen = myGen();

(async() => {
  for (let n of gen) {
    await new Promise(resolve => {
      setTimeout(() => {
        console.log(n);
        resolve()
      }, 1500)
    })
  }
})();
Melodize answered 13/1, 2018 at 15:37 Comment(0)
N
3

Another way is to use the relatively new AsyncGenerator feature
https://github.com/tc39/proposal-async-iteration

I think it abstracts the problem nicely (creating an iterator that sleeps in between each iteration).

async function* sleepGenerator(numSleeps, sleepMillis) {
    for (let i = 0; i < numSleeps; i++) {
        await sleep(sleepMillis);
        yield {i, numSleeps, sleepMillis};
    }
}

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

(async function run() {
    for await (const iterMeta of sleepGenerator(5, 500)) {
        console.log(iterMeta);
    }
})();
Northway answered 30/8, 2018 at 20:58 Comment(0)
J
1

just, store the nextValue

function* myGen(){
    let counter = 0;
    for(let i = 0 ; i <= 10; i++){
        yield counter++;    
    }
}

const gen = myGen();
const start = setInterval(() => {
    let nextValue = gen.next();
    if(nextValue.done){
        clearInterval(start);
    } else {
        console.log(nextValue.value);  
    }
}, 1500)
Jodijodie answered 13/1, 2018 at 15:30 Comment(0)
G
1
function* myGen(){
let counter = 0;
for(let i = 0 ; i <= 10; i++){
    yield counter++;    
}
}

const gen = myGen();
const start = setInterval(() => {
var genObj=gen.next();//keep next result as an object to avoid use next method twice

if(genObj.done){
    clearInterval(start);
} else {
    console.log(genObj.value);  
}
}, 1500)//I spent an hour learning this,late but get some konwledge,so,thanks.
Gruver answered 13/1, 2018 at 17:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.