gulpjs / async-done

Allows libraries to handle various caller provided asynchronous functions uniformly. Maps promises, observables, child processes and streams, and callbacks to callback style.
MIT License
70 stars 21 forks source link

add generators support #22

Closed tunnckoCore closed 9 years ago

tunnckoCore commented 9 years ago

21 like that?

and just allow failures for 0.10 testing

tunnckoCore commented 9 years ago

wohoo.. with node_modules/.bin/gnode node_modules/.bin/lab test/*.js -cv almost works.. runs the generators tests but tests fails

so yea, should allow failures not only because the promises. but think it.. who will use generators and promises in 0.10, it's not purpose of this lib. 99% of the cases would use promises and generators in already mainstream 0.12 or > 1.0

tunnckoCore commented 9 years ago

@phated this would be possible, and gulp would have generators support out of the box

var request = require('cogent');
var Undertaker = require('undertaker')
var taker = new Undertaker();

taker.task('task1', function * () {
  var res = yield * request('https://www.google.com')
  console.log(res)
});

interesting... tests pass and only because that The following leaks were detected:Set, Map exits with 1 and the builds fails https://travis-ci.org/chorks/async-done/builds/65021471

phated commented 9 years ago

I am thinking about this more and more and I feel like generators are being under-utilized here.

Imagine if there were an async-done-style library that worked with generators. e.g. you could yield a stream, or an observable, or a promise, or all three and it would handle the iteration and waiting. This would be far better than promise-only implementations like co or when/generator. It could even resolve to a promise to allow await syntax when it arrives.

tunnckoCore commented 9 years ago

I dont know, it is up to you. I think it would be useful for users and one day will want it I'm almost sure. And worth nothing more than co which is cool exactly because the way it handles the generators flow. Cuz for example in lukehoban/ecmascript-asyncawait#spawning have another implementation in just 25 lines, but won't work as most users would expect, because the co philosophy.

above spawn working from 0.10 to current

gens.js

'use strict'
var Promise = require('native-or-bluebird')

function spawn (genF) {
  return new Promise(function (resolve, reject) {
    var gen = genF()
    function step (nextF) {
      var next
      try {
        next = nextF()
      } catch(e) {
        // finished with failure, reject the promise
        reject(e)
        return
      }
      if (next.done) {
        // finished with success, resolve the promise
        resolve(next.value)
        return
      }
      // not finished, chain off the yielded promise and `step` again
      Promise.cast(next.value).then(function (v) {
        step(function () { return gen.next(v) })
      }, function (e) {
        step(function () { return gen.throw(e) })
      })
    }
    step(function () { return gen.next(undefined) })
  })
}

var cnt = 10
spawn(function * () {
  return yield {
    foo: yield Promise.resolve(cnt + 20),
    bar: yield Promise.resolve(cnt + 30)
  }
})
.then(console.log)
.catch(console.error)

node 0.10, using gnode executable

gnode gens.js
{ foo: 30, bar: 40 }

node 0.12, using harmony flag

node --harmony gens.js
{ foo: 30, bar: 40 }

iojs

node gens.js
{ foo: 30, bar: 40 }

The signature is same as co, but yea cant be run on 0.10, cuz co is built on native promise, which is .. hm.

Okey.. as you decide, as I said it will be feature request one day. As I mentioned I'm thinking to start work on new control flow lib like them, but with backward compatibility to 0.10 -- working in both sides with callback style and promise style.