Wait.for: Sequential programming for Node.js (beta) (github.com)
Simple, straightforward abstraction over Fibers.
By using wait.for, you can call any nodejs standard async function in sequential/Sync mode, waiting for result data, without blocking node's event loop (thanks to fibers)
I'm looking for real-world node apps, to test wait.for
36 comments
[ 5.5 ms ] story [ 90.6 ms ] threadfor what it's worth, I also refuse to use or depend on any code that makes use of node-fibers. I know i'm far from the only person who feels that way too.
http://en.wikipedia.org/wiki/Fiber_(computer_science)
in node.js, fibers are... http://sstur.com/pres-fibers
wait.for(fs.readfile,'/etc/passwd') == fs.readfileSync('/etc/passwd')
wait.for allows you to call any async function as if it were a sync function, without blocking node's event loop. It works inside a fiber. Check the examples.
You don't have to wrap all your code in a call to `Fiber()`
full classic node-server sample:
That is probably a worthwhile tradeoff, but the first time I read through it, that mechanic wasn't obvious to me.
Today launchFiber is calling the fn inside a Fiber(), tomorrow could be launching the fiber by means of a generator.
The idea was to create a very simple abstraction to avoid callback hell, adding low or no complexity, and keeping the flexibility to use all the existing async fns with a callback or just "wait" for the results.
the code is here: https://github.com/luciotato/waitfor/blob/master/waitfor.js, but it does require fibers.
Generators are provided by V8, don't require an external fibers extension (i.e. hack), and will be available in the next node stable via `node --harmony-generators`.
Here's an example for those interested: https://github.com/visionmedia/co
- wait.for it's simpler
- wait.for uses try/catch
I don't know async.series deeply, but, ¿how do you use results from the first function on the second or third?
wait.for:
async.series: async has a lot of functionality. You can use wait.for and async at the same time. They supply different functionality.Example:
waterfall
The other problem that comes up is the difficulty of getting a backtrace beyond the current callback. It can be hard to troubleshoot an error in a callback when you can't look back at how the async call got started. In such cases what you really want is a list of backtraces that capture all the relevant history. I seem to recall that people have come up with solutions for this, but can't remember what they are. Maybe someone else can comment?
The stack trace is a pain for those operations, and any error that occurs as part of "normal" javascript operation (e.g. ReferenceError) has to be handled like a normal exception, which makes the style inconsistent and therefore a bit harder to manage.
I think that the latest or upcoming version of Node is presenting a solution to this in the form of domains, but I'm not too familiar with it.
It seems like the kind of problem that is better dealt with by a compiler.
I haven't had too much experience with Domains, but I believe they are generally used for courser grain error handling (because it's a bit verbose to attach them all over the place). E.g., to catch most errors (it's no guarantee what 3p libs do to your context) generated in fulfillment of a particular web request.
Also, do any of the promises libraries solve the backtrace problem, and if so how do they do it?
You're right that you have to manage exceptions, which is difficult. The biggest problem I've had with Node is the runtime exceptions that crash the entire process because they go uncaught. To deal with that, I have the server automatically restart on failure - far from an ideal scenario of error recovery (and what I think you're referring to when you talk about sacrificing error safety).
However, in practice you want a higher level of abstraction, since multiple async calls typically end up mapping to one sync call. This applies to streams in particular where you need to wait until they become readable.
I've written Common Node (https://github.com/olegp/common-node) to do just this and made it CommonJS and RingoJS compatible, which means the code written for Common Node runs on both V8 and the JVM. We've been using it in production at https://starthq.com for a while with great success. Due to some optimizations we put in place, Common Node actually performs faster than Node in some benchmarks.
> then you can deprecate almost half the functions at: http://nodejs.org/api/fs.html (clue: the Sync versions)
Not quite. I use the Sync versions not to avoid callbacks, but to ensure that nothing else happens while I'm doing the operation. For example, take a look at the Database.reload function from this project (a NoSQL database written in Node): https://github.com/phusion/zangetsu/blob/master/lib/zangetsu.... Reloading the database contents involves traversing multiple directories and reading multiple files. While reloading the database contents, I do not want the database to be modified. With asynchrony, the amount of different states that I have to be aware of rises so quickly that it's much, MUCH easier to use sync calls and tell the user "reloading is not concurrent, deal with it; at least it's correct". Wait.for does not solve this problem.
It seems people believe that you can't run into concurrency problems or race conditions because Node is single threaded. This is false. I even had to write my own locks (https://github.com/phusion/zangetsu/blob/master/lib/zangetsu...) because Node doesn't provide one.
I'll just leave this here. It's been my pet project for the last couple years, and is a fully featured version of this concept.
There's also https://github.com/0ctave/node-sync, which is the same concept.