2

I'm trying to stop the execution flow on the setTimeOut using generators. What am I doing wrong? I can`t get the console.log out each 1500 ms. I'm new on node, please don't telepathically kill me if I'm doing a very stupid thing

['1', '2', '3'].forEach(function* iteration(index) {
  // Some logic here
  yield setTimeout(() => console.log('sick of this!'), 1500)
  iteration.next(index)
})
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
thorstorm
  • 153
  • 3
  • 10
  • Most importantly, `setTimeout` doesn't return anything that you could `yield` or even await - use a promise. Next, a generator is nothing asynchronous, if you want it like that then you have to use a special runner (like the `co` library). Last, `iteration` doesn't have a `next` method – Bergi Jul 08 '16 at 12:52
  • Disregarding your issues with generators, this sounds like a duplicate of [Using async/await with a forEach loop](http://stackoverflow.com/q/37576685/1048572) – Bergi Jul 08 '16 at 12:55

2 Answers2

1

The sad thing is you can't. Array.prototype.forEach is a higher level function, it just calls the given callback, but will not and cannot take generators. I mean you can give a generator as generators are just normal functions, but they will not run, and you can't yield values.

The second thing is that you would just yield timeoutId-s, and I am pretty sure you wanted to wait for 1500 ms.

So you will have to get rid of forEach and use for..of instead, and will have to write a delay function, using async/await it would look like:

function delay(time, value) {
  return new Promise(resolve => { setTimeout(() => { resolve(value); }, time); });
}

async function main() {
  for (var item of ['1', '2', '3']) {
    await delay(1000);
    console.log(item);
  }
}

main().then(null, e => console.error(e));

You can transpile it with babel.

If you wish to use regular node callbacks, that is a bit harder and not so nice, but definitely possible. If you are allowed to choose, I suggest you to use the async/await way.

Tamas Hegedus
  • 28,755
  • 12
  • 63
  • 97
0

May be you can do like this;

['1', '2', '3'].forEach(e => { function *iteration(index) {
                                 // Some logic here
                                 var val = yield setTimeout(_ => it.next(index),0); // make async
                                 setTimeout(_ => console.log('sick of this..! '+ val), 1500*val);
                               }
                               var it = iteration(e);
                               it.next(); // start the engine
                             });

or as suggested asynchronizing by ES6 promise job queue

['1', '2', '3'].forEach(e => {function *iteration(index) {
                                // Some logic here
                                var val = yield Promise.resolve(index).then(v => it.next(v)); // async by the job queue
                                setTimeout(_ => console.log('sick of this..! '+ val), 1500*val);
                              }
                              var it = iteration(e);
                              it.next(); // start the engine
                             });
Redu
  • 25,060
  • 6
  • 56
  • 76