bjouhier / galaxy

Cosmic harmony with callbacks and generators
http://bjouhier.wordpress.com/2013/06/01/bringing-asyncawait-to-life-in-javascript/
145 stars 6 forks source link

alternative to galaxy.spin() #12

Open jampy opened 10 years ago

jampy commented 10 years ago

When I want to execute three functions in parallel, AFAIK I have to to use forEachStar (which I don't fully understand yet due to lack of documentation) or write something like this:

  // just a silly placeholder for some asynchroneous generator:
  var delay = galaxy.star(function (delay, callback) {
    setTimeout(function() {
      callback(null);
    }, delay);
  });

  // start three operations in parallel (think of three different database updates)
  var par1 = galaxy.spin(delay(500));
  var par2 = galaxy.spin(delay(500));
  var par3 = galaxy.spin(delay(500));

  yield par1();
  yield par2();
  yield par3();

Instead, couldn't you allow to pass an array to yield with all generators that must complete in parallel?

  yield [ delay(500), delay(500), delay(500) ];

That would be much shorter. I'd also expect that yield would return immediately should one of the operations throw an error.

Also, if the results of these generators are required, give them back as an array:

  var results = yield [ delay(500), delay(500), delay(500) ];
   // or, ES6 style:
  [ some, foo, bar ] = yield [ delay(500), delay(500), delay(500) ];

What do you think?

PS: Compliments, great work! This is the solution I like the most (to simulate synchroneous programming).

bjouhier commented 10 years ago

That's a cool idea. I'm not sure it is that easy to implement but I'll investigate.

In the mean time, you can solve this with mapStar:

// don't forget the yield before `mapStar`
var results = yield [500, 500, 500].mapStar(3, function*(ms) {
  // don't forget the yield here either
  return yield delay(ms);
});

The galaxy.spin calls are not needed any more because parallelization is done by mapStar but this is still very heavy compared to your array proposal.

bjouhier commented 10 years ago

I gave it a try as it seemed rather easy to implement (and not risky because an exception was thrown in this case).

This is really a cool idea :smile:

If it works (you can try by pulling from git) I'll publish to NPM but I need to write a few unit tests first.

jampy commented 10 years ago

Awesome! Thanks so much :)

bjouhier commented 10 years ago

I'll need to improve it because it does not return immediately if an operation throws an error. For example, if the first operation succeeds after 1000 ms and the second one fails after 500 ms, it will fail after 1000 ms.

But that won't impact the syntax.

jampy commented 10 years ago

Yeah, that would be important. Is that difficult to implement?

bjouhier commented 10 years ago

Not, it is not really hard but I won't have time today (I have a job).

jampy commented 10 years ago

Of course. No hurry :)