S
Spion
spion.github.io · Personal blog · on HN since 2013
Spion writes about JavaScript and Node.js, mainly async patterns, promises versus callbacks, and their performance and debugging tradeoffs.
What HN saysHN commenters cite it in discussions of promises, bluebird and async/await, and link the post on promises plus generators as a way to avoid callback hell.
15HN people shared it
6linked it in comments
11stories submitted
232story points
9 years agolast shared
2013people per year2026
Most-shared posts
- 1Analysis of Complexity, Performance, and Debugability of Async Patterns in Node7 people · 13 points · first shared 2013 · discussion on HN
- 2Why I am switching to promises5 people · 128 points · first shared 2013 · 90 comments on HN
- 3ES7 async functions – a step in the wrong direction (2015)4 people · 85 points · first shared 2015 · 39 comments on HN
- 4JavaScript isn't cancer2 people · 4 points · first shared 2016 · 2 comments on HN
- 5Machine learning ethics1 people · 2 points · first shared 2018 · discussion on HN
What HN people wrote when they linked it
spion · 2014-11-27
Hmm, those are strange results indeed. I would not be surprised if those measurements were made a year ago. Back then, promises were really slow.
But then bluebird came out and changed everything, and many of the other promise libraries followed suit. Most promise libs are now really lightweight (with the only remaining exception being Q).
See https://gist.github.com/spion/6990910 ; http://spion.github.io/posts/why-i-am-switching-to-promises.html ; https://github.com/spion/async-compare/blob/master/latest-results.md -
For example, bluebird (and most other promise libraries today) have 2 to 3 times lower overhead than caolan's async and are comparable to the most hand-optimized raw callbacks.
hdhzy · 2017-10-03
Async await while looking nice compared to bare callbacks and Promises are still not without drawbacks. For example one cannot use await inside nested callback so it's in async functions it's necessary to use for-of and avoid forEach when dealing with Promise values.
* http://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-functi…
* https://spion.github.io/posts/es7-async-await-step-in-the-wrong-direct…
Current solution is just an evolutionary change merging generators and Promises.
inglor · 2016-06-02
There's https://github.com/zenparsing/es-typed-catch to solve the problem I raised here 3 years ago: https://esdiscuss.org/topic/try-catch-conditional-exceptions-in-light-… and there's a good writeup on problems with async/await by fellow bluebird contributor Gorgi Kosev (spion) here: https://spion.github.io/posts/es7-async-await-step-in-the-wrong-direct… (Although I don't really agree with it)
JoshGlazebrook · 2013-12-17
Have you looked into bluebird[1]? It and most of the available promise libraries have a nodify-esque function where you can simple do this:
var fs = Promise.promisifyAll(require("fs"));
And all of the regular methods in fs are now promisable. Q also seems to be one of the slowest[2] promise libraries there is. I'm not sure why so many people use it. That guy has a rather large benchmark table from a couple months ago as well and Q seems to be shockingly slow compared to the dozen or so other promise libraries out there.
1. https://github.com/petkaantonov/bluebird
2. http://spion.github.io/posts/why-i-am-switching-to-promises.html
hiddentao · 2014-07-20
On the topic of using callbacks, promises + generators will enable you to do the same job with almost the same level of performance (see http://spion.github.io/posts/why-i-am-switching-to-promises.html) whilst avoiding callback hell and having to perform error handling in multiple places.
A good Promise library (like https://github.com/petkaantonov/bluebird) even provides mechanisms for writing functions that both return Promises as well as accept callbacks, allowing your API client to choose how they wish to use it.
Also, beware of making a function "asynchronous" by simply having it accept a callback parameter, e.g.:
function myFunc(v, cb) {
someOtherObject.v = v;
cb();
}
myFunc(5, function(err) {
if (err) return console.error(err);
console.log('call done');
});
console.log('call started');
In the above code, you'll see "call done" before you see "call started" because myFunc() isn't really functioning asynchronously.
This is yet another reason to use a good Promise library like Bluebird, as it ensures that even if you wrap a synchronous function inside a Promise the resulting execution will flow as if it was asynchronous.
abecedarius · 2013-08-31
"the debugging story for generators is somewhat bad, especially because of the missing stack traces for thrown errors. Fortunately, there are solutions and workarounds, like those implemented by genny (obtrusive, reduces performance) and galaxy (unobtrusive, but requires native modules)."
From the post you brought up, http://spion.github.io/posts/analysis-generators-and-other-async-patte… -- by the author of Genny. As I said, that's at least qualitatively the same as Q; quantitatively I haven't looked. At https://github.com/spion/genny there's the example line
require('genny').longStackSupport = true
and "This results with CPU overhead of approximately 500% and memory overhead of approximately 40%. In the future, the overhead will probably be eliminated in node but not in browsers." The benchmark post says Catcher is worse.
The README for Q shows the same switch and says "This feature does come with somewhat-serious performance and memory overhead,
however. If you're working with lots of promises, or trying to scale a server
to many users, you should probably keep it off. But in development, go for it!"
I'm not a current user of any of these systems, but this is why I said the first-order cause of any performance difference appears to be that ClojureScript is not a library.