And they're completely equivalent. Why would someone actually like the latter, except you're forced to use it because of the prevalence of JavaScript?
`asyncio` is not only easier to use than the traditional "manual" state machines with classes, but also much faster than something like `Twisted`. In my crappy local benchmark[1], it easily beat `Twisted` in a considerable margin. That may be because of the flaws in my test code, but still their performance is on par. I see no points in relying on callback hell, at least in Python, except the lack of the libraries that support asyncio, which makes me a little bit sad.
Yeah but node.js predates asyncio by about 5 years. Python was early to the game with asyncore and Twisted (circa early 2000's), but the async I/O support stagnated and left a big hole for node.js.
Part of the reason for stagnation was because you really need new language features -- i.e. yield/send, yield from, etc. JavaScript already had the necessary language features for its concurrency model.
That's a good point. I also think `asyncio` was way too late in the game. I just wanted to mention the feature that was missed from your comment, which I think is not fair to Python.
Coroutines are much better suited to event driven, non blocking IO code. Sorry for the shameless plug but I recently released my hobby project that uses Lua coroutines for nonblocking HTTP server: https://github.com/raksoras/luaw
Lua was quite pleasant to work with in this context!
One thing yield/await does is that if plays nice with existing control-flow mechanisms in the language. You can put them inside a for loop, if statement, try-catch block, etc. With promises all of those have to be reimplemented in a library and all your code needs to be converted to the "promisified" version of things.
The different syntax also prevents you from creating functions that can be reused by both sync and async code.
The big thing promises and other callback-based control flow libraries do is that they fix exception handling in async code (its a PITA to add error handlers in every callback when writing async code by hand). They also let you avoid some of the awkward "pyramid of doom" nesting but thats not really killer feature because you can also achieve that by using tons of named functions.
async/await are coming with ES7 and available today with BabelJS and other transpilers. Though not part of core, they rely on thenables/promises, which handle the reject/resolve which get composed with generators.
The required bits are in place... alternatively you can use co/koa which uses generators along with yeilding promises to act in a similar fashion.. it does work pretty well, and will only get better.
I do think promise and deferred are huge improvements to ergonomics, but still... I cannot completely love the code bloat (which is much smaller and easier to reason about than callback hell, of course) that is caused by those libraries. I much prefer Haskell's monadic interface or Python's `yield from`. But that may be my personal preference.
Grownups in charge of the lang are listening and they're doing their best to incorporate these features (async/yield) in the language as soon as possible.
And that's why Python supports `asyncio` (not to be confused with `asyncore` which is obsolete). So I prefer:
to this callback hell: And they're completely equivalent. Why would someone actually like the latter, except you're forced to use it because of the prevalence of JavaScript?`asyncio` is not only easier to use than the traditional "manual" state machines with classes, but also much faster than something like `Twisted`. In my crappy local benchmark[1], it easily beat `Twisted` in a considerable margin. That may be because of the flaws in my test code, but still their performance is on par. I see no points in relying on callback hell, at least in Python, except the lack of the libraries that support asyncio, which makes me a little bit sad.
[1] https://github.com/barosl/ws-bench