NG
NG copied to clipboard
What about the `co` approach?
Recently co moved to using promises, or more specifically yielding promises.
https://github.com/tj/co
There's been talk of having APIs in NG return promises. What are the downsides/upsides of return vs. yield?
@domenic probably has things to say.
This is a false dilemma. All functions would return promises. Consumers could consume them either with:
.thendirectlyyield, if inside a wrapper function likeco()orQ.spawn()orBluebird.async()await, if inside an ES2016asyncfunction.
yield is kind of a hack in this way, but a cool one. By wrapping your generator function in co() or whatever, you make yield inside your generator function no longer yield items in a lazy sequence, but instead do control-flow stuff. async + await is the more principled version of this.
A more interesting question is whether NG would want to provide a standard co()/spawn()/async() function or set of functions, as a sort of polyfill for async functions. Seems pretty OK.
Personally I don't like the generator hack as first-class thing. It's primarily a good compilation target / temporary implementation of await.
The first goal for NG should be to return a Promise every time async work is done. That's sufficient in the short term. It enables composition, paves the way for the future, and enables fairly straightforward transpilation in the mean time (specially now with generators enabled by default).
+1 to @rauchg
IMHO first goal should just be to release a version that replaces stdlib errbacks with returning Promises. There are lots of errbacks in the node stdlib, so that's a lot of sheds to paint in a first pass anyway.
Promises instead of errbacks are an important improvement because it makes 'throw' and 'return' useful again.
You still get crazy 'then' chains instead of pyramids of doom, and that is where async/await and async functions can help. See: http://jakearchibald.com/2014/es7-async-functions/
But to your question of "What are the downsides/upsides of return vs. yield?". Yield provides a path to 'return' several times
Once ES2016, the only time I expect to write yield directly is when creating readable-stream-like things. e.g.
async function * longPollSocket({ url, initialEventId }) {
let eventId = initialEventId;
while (let res = await fetch(url + '?since='+eventId)) {
eventId = res.body.eventId;
let msg = res.body.data;
yield msg;
}
}
// iterates async..
for (var msg on longPollSocket(opts)) {
console.log('msg after some time');
}
(inspired by jhusain/asyncgenerator)
Notably, co inherently doesn't really try to help you take advantage of this aspect of Generators (multiple, yields). By returning a promise of a single value that is resolved only once all the yields in your generator are done, it's gives up on any potential of multiple async events.
@gobengo this is because promises represent a single value. You can yield multiple values though:
let [r1, r2] = yield Promise.all([p1, p2]);
For example. I agree with Domenic - a co like approach is just returning promises :)
see also https://github.com/jhusain/compositional-functions/issues
Isn't the beauty of the callback/errback approach is that it works with any other abstraction people want to apply to it? This would turn node core from a low level utility belt, to an opinionated thing - I kind of like it how if we want promises for the fs module, we just install a package and now I have promises for fs.
What are the gains of switching from errbacks?
@balupton not at all. First of all, you can convert any api that follows some sort of standard or convention automatically to something else. Secondly callbacks do not follow any single standard or convention, not even within node core itself and especially not in the wild.
I'm currently working on a standardized low-level API for Node as part of a future API Compliance WG. My plan is that the current API will be built on top of this, also allowing simple interface extensions in the future. Basically, I'm not against including a Promise based interface for the API, but it won't be the interface directly into C++.
+1 return promises everywhere!