Javascript ES6 async generator

I need to run the async generator (I need to get the result in the console 1,2,3,4,5, because now I have 4,1,2,3,5), can anyone help me? I need to run a task and wait for the previous task to complete before it launches the next task. I need to use (if possible: only) generators (or generator + promise?)

Here is my code

/*jshint esnext: true */ function show(msg) { var _msg = msg; setTimeout(function() { console.log(_msg);}, 2000); } function show2(msg) { console.log(msg); } var stack = []; // add some function to stack stack.push(function() { show(1); }); stack.push(function() { show(2); }); stack.push(function() { show(3); }); stack.push(function() { show2(4); }); stack.push(function() { show(5); }); function* generator1() { for(var key of stack) { yield key(); } } var gen = generator1(); gen.next(); gen.next(); gen.next(); gen.next(); gen.next(); 
+5
source share
3 answers

This can be done cleanly with the generator. Here is an example of one approach in which we move .next() to the timeout itself to ensure that it does not happen sooner. In addition, the generator now returns a function from the stack instead of executing it, because you cannot call the .next() generator from the execution of the generator itself.

It is worth noting here that this is probably not the case as I would have done it β€œin the wild”; I would include promises. But you asked if this can only be done with a generator - the answer is yes.

 function show(msg) { var _msg = msg; setTimeout(function() { console.log(_msg); execute(); }, 2000); } function show2(msg) { console.log(msg); execute(); } var stack = []; function execute() { var fn = gen.next().value; if (fn) fn(); } // add some function to stack stack.push(function() { show(1); }); stack.push(function() { show(2); }); stack.push(function() { show(3); }); stack.push(function() { show2(4); }); stack.push(function() { show(5); }); function* generator1() { for(var key of stack) { yield key; } } var gen = generator1(); execute(); 

http://jsfiddle.net/smmccrohan/k271gz7o/

+4
source

There are many functions performed by "tasks" for this, you can even write your own. But for this you will have to use Promises, not setTimeout . Here is a quick example:

 function delay (ms, val) { return new Promise(function (res) { setTimeout(res, ms || 1000, val || Math.random()); }); } function* run () { yield delay(); console.log(yield delay()); yield delay(); console.log('foo'); // sync calls anywhere in between console.log(yield delay()); } function async(gen){ "use strict"; gen = gen(); return Promise.resolve().then(function cont(a){ var n = gen.next(a), v = Promise.resolve(n.value); if(n.done) return v; // a `return` return n.value.catch(gen.throw.bind(gen)).then(cont); }); }; async(run); 

Basically, we call the next method of the generator, waiting for it to finish, and then run the next method again and overwrite until the generator stops.

Bluebird has a more fault-tolerant feature called Promise.coroutine .

Task.js: http://taskjs.org/ provides a function specifically for this.

Hope this helps!

+2
source

You need your functions to tell when they are finished. Promises are a good way to solve this problem.

I will stick with your source code as much as I can:

 function show(msg) { return new Promise(function(resolve){ var _msg = msg; setTimeout(function() { console.log(_msg); resolve(_msg);}, 2000); }); } function show2(msg) { return new Promise(function(resolve){ console.log(msg); resolve(msg); }); } var stack = []; // add some function to stack stack.push(function() { return show(1); }); stack.push(function() { return show(2); }); stack.push(function() { return show(3); }); stack.push(function() { return show2(4); }); stack.push(function() { return show(5); }); function* generator1() { for(var key of stack) { yield key(); } } var gen = generator1(); gen.next().value.then(function(){ gen.next().value.then(function(){ gen.next().value.then(function(){ gen.next().value.then(function(){ gen.next(); }); }); }); }); 

Of course, it looks ugly and can be improved. As mentioned in another answer, there are task runners and flow control libraries like task.js , gen-run and co .

With co last part will be:

 co(generator1); 
+1
source

All Articles