5 ms·
Faking Co-Routines, or Why Callback Hell Is Over (2014)
- teddyh 11y agoWhat’s with the HUGE FONT SIZE?
- pspeter3 11y agoI still don't get why async/await is inherently better than using Promises/Streams. Is it purely a syntax difference or is there a semantic difference as well?
- jestar_jokin 11y agoI believe async/await uses promises behind the scenes. It just means invoking code looks nicer, i.e writing "var res1 = await prom1(a); await prom2(a, res1)" is marginally cleaner than "return prom1(a).then((res1) => prom2(a, res1));", in the sense that you're just writing statements rather than chaining method invocations.
- erikpukinskis 11y agoI have yet to see an "improvement" on callbacks, whether it's promises or fibers or generators, where the benefit in readability is worth the havoc it wreaks on my ability to debug the program. These days I write JavaScript using only functions, literals, variables, and the occasional prototype and it's amazing. I think many programmers have a desire to believe they are working on complex problems that demand sophisticated tools. I remember learning Ruby and being excited whenever I found a reason to write a DSL. In retrospect it was unnecessary every time. In every case the code would've been clearer if I had just stuck with functions and kept refactoring until I had the right interfaces and data structures. It helps to remember function a() { b(function() { //etc }) } is equivalent to function a() { b(c) } function c() { //etc } which is not particularly more verbose. And as a side benefit, refactoring that way gives you an opportunity to make c() self-documenting.
- cyphar 11y ago> It helps to remember > function a() { b(function() { //etc }) } is equivalent to > function a() { b(c) } function c() { //etc } which is not particularly more verbose. And as a side benefit, refactoring that way gives you an opportunity to make c() self-documenting. It's not always equivalent, since you can have closures.
- erikpukinskis 11y agoThat's true, and I use closures sometimes. But they are a performance and readability anti-pattern, and it's often better to either pass in or bind the data you actually need. In some sense closures are globals and globals are bad.
- jestar_jokin 11y agoUnfortunately, Node.js decided that every callback should accept an error as the first argument to every callback. If you're chaining a bunch of callbacks, it's tedious and error-prone to add boilerplate to check for an error and handle it consistently in every callback, and violating the DRY principle. It's not easy to simply propagate the error to a higher-level handler.
- fao_ 11y agoIf you're repeating yourself, then you could possibly abuse higher class functions to automatically generate error handling?
- doublerebel 11y agoYes, there are libs like errTo [1] and iced-error/make_esc [2]. Not to mention Promise.promisify(). Long solved problem. [1]: https://www.npmjs.com/package/errto https://www.npmjs.com/package/errto [2]: https://www.npmjs.com/package/iced-error https://www.npmjs.com/package/iced-error
- apeace 11y agoI find the `async` library excels at this: var fs = require('fs'); var async = require('async'); async.waterfall([ (cb) => fs.readFile('foo.txt', cb), (data, cb) => my_function(data, cb), (result, cb) => myDb.lookup(result, cb), ], (err, finalResult) { if (err) { console.error(err); } else { console.log(finalResult); } }); There are all sorts of helpful async primitives in there. I don't write Javascript without it! Here is a link to the documentation: https://github.com/caolan/async https://github.com/caolan/async
- Azkar 11y agoI don't understand why he talks about a javascript problem being solved, then goes on to show us examples in coffee script.
- ludamad 11y agoThere really shouldn't be an difficulty seeing how it maps to JavaScript. CoffeeScript is pretty clean for code examples.
- Azkar 11y agoIt's not that it's difficult to understand, it's about comparing apples to apples.
- jacobolus 11y agoPaste the code into here if you’re having trouble following: http://coffeescript.org/#try:%7BliftAll%7D%20%3D%20require%20%22when%2Fnode%22%0A%7Bcall%7D%20%3D%20require%20%22when%2Fgenerator%22%0A%7BreadFile%2C%20writeFile%7D%20%3D%20(liftAll%20require%20%22fs%22)%0Amarked%20%3D%20require%20%22marked%22%0A%0Acall%20-%3E%0A%20%20try%0A%20%20%20%20buffer%20%3D%20yield%20readFile%20%22my-blog-post.md%22%0A%20%20%20%20html%20%3D%20marked%20buffer.toString()%0A%20%20%20%20yield%20writeFile%20%22my-blog-post.html%22%2C%20html%0A%20%20catch%20error%0A%20%20%20%20console.log%20%22%23%7Berror%7D%22 http://coffeescript.org/#try:%7BliftAll%7D%20%3D%20require%2...
- amelius 11y agoThe problem with javascript coroutines is that you can only yield from within the generator itself, not from a called function. This makes it impossible, for instance, to write a nice I/O library that is to be called from within a generator (the library is supposed to yield on a blocking situation).
- outside1234 11y agoPlease: Do not use CoffeeScript in your examples. It is not common to have "readability" in CoffeeScript and it restricts a significant number of readers from being able to understand the code sample.
- mchahn 11y ago> restricts a significant number of readers from being able to understand Can you seriously say you can't read it? It seemed easy to me.
- scriby 11y agohttps://github.com/scriby/asyncblock-generators https://github.com/scriby/asyncblock-generators That's a control flow solution I wrote on top of generators to make it a little easier to manage parallel tasks, timeouts, error handling, and so on. I originally made asyncblock, which was based on fibers a few years ago. This module uses the same underpinnings as asyncblock, just based in generators instead of fibers.
- raspasov 11y agoUse ClojureScript + core.async and get some work done.
- hellofunk 11y agoAbsolutely, cljs is a top-shelf way to work in JS. And core.async is fantastic.