Node.js: Awesome Runtime and New Age JavaScript Gospel

I am a big fan of node.js but I have a big problem with the core team. No need to hide it and pretend everything is OK. The fibers vs. callback war erupted again this week on the mailing list, with new ballistic benchmark missiles fired from both sides and showers of sarcasms.

This is ridiculous. Time to sit down and blog about it!

Awesome Runtime

Node is an awesome runtime. It is simple; it is fast; it is 100% asynchronous; it is JavaScript. These are the things that make it so attractive for people like me. I’m sold on the “end to end JavaScript” story and node is an important piece of that story. I’ve also done my share of classical thread programming (Java, .NET) and I’m now deeply convinced that async is the way to go.

Node also comes with a good package system that manages dependencies in a very decoupled way and a simple tool to publish, install and update packages. I also like the fact that most components are published under the very liberal MIT license and that Windows, which is important for us, is supported as a first class platform.

Definitely, node.js is an an awesome runtime. I’m not regretting one single day to have chosen it for one of our projects.

New Age JavaScript Gospel

So the core team does a great job on the runtime but it seems invested with another mission: evangelizing a new way of programming, based on callbacks, streams and pipes.

To develop on node, you have to learn callbacks because this is how JavaScript deals with asynchronous code. You may find it hard but you are wrong:

It is not hard, you just need to learn callbacks.

Also, some people may tell you that they have found ways to ease your pain, but you should not listen to them; they are just heretics who are trying to divert you from the true and only way to node.

You *have* to learn callbacks!

So you will learn callbacks! And you’ll probably find out that they are not so hard after all. It is mostly a question of knowing a few patterns and applying them. It is more painful than hard. But it is also more error prone; it forces you to write more code; and the code is more difficult to read and modify because of all the “pattern noise”.

You’ll probably think that all this might be fine for a personal project but that it doesn’t scale well to large projects. Costs will rise at all levels: training costs to get people up to speed with callbacks, development costs because of extra code to write and of more difficult code reviews, quality costs because of more fragile code, maintenance costs, etc.

So, you may come back to the mailing list with a question like:

Fine, now I understand callbacks but I still have problems. Isn’t there a better way?

And you’ll get the same answer:

No. Callbacks are perfectly fine! You just need to refactor your logic and you should try to reformulate your problem with streams and pipes.

And don’t listen to the sirens who say that that they have solutions for you and that you shouldn’t bother with callbacks.

You *have* to learn callbacks and streams!

Someone might add:

Your application is probably not a good fit for node. You should have chosen PHP or Ruby instead.

But you want to use node because you like JavaScript and node’s asynchronous model.

I don’t know what you’ll do at this point. One possibility is that you’ll follow the party line: you will write a stream. It might not solve the problem you were trying to solve in the first place but you’ll be able to post your success story on the mailing list and you’ll get plenty of kudos from the core team.

The worst is that this is hardly a caricature. Node is not just a runtime; it comes with a gospel:

You have to program with callbacks and you have to rethink your application as streams and pipes.

The gospel is wrong!

Asynchronous !== Callbacks

Part of the problem comes from an unfortunate identification between asynchronous programming and callbacks. Asynchronous programming and callbacks are seen by many as one and the same thing. For them, programming asynchronously means programming with callbacks.

This is just plain wrong: asynchronism is the essence of node while callbacks are just an accident of node. They belong to different levels.

Asynchronism is a behavior. It is essential in node because node is all about performance and asynchronous I/O. Synchronous (blocking) I/O is a disaster for node.

Callbacks are just an artifact that JavaScript gives us to deal with asynchronous behaviors. Today, JavaScript only gives us this artifact, but tomorrow it will give us other artifacts: generators and yield. Callbacks are just an accident.

And, BTW, callbacks are probably not the best artifact to express asynchronism because they are *not* essentially asynchronous. Just consider the callbacks passed to Array.prototype.forEach: those are invoked synchronously.

IMO, the artifact that I have introduced in streamline.js (the _ marker), and that has been the target of so many sarcastic comments on the mailing list, is a better artifact because it captures the essence of asynchronism in code (the points where execution yields). So, in a sense, streamline.js provides a cleaner model for asynchronous programming than callbacks.

Every piece of software is not a proxy

The nirvana of node’s gospel is a program built entirely with streams and pipes. This comes from a vision that every piece of software can be thought of as being some kind of proxy and that systems can be built by connecting streams with pipes. This is a very appealing vision and it would just be so great if it would apply to every domain.

It does not!

The streams and pipes vision will likely work well in domains that are naturally event driven. This is the case of most front-end systems. But what about back-end systems? Most of the time these are more goal driven than event driven: they don’t push much data to other layers; instead, they respond to requests/questions by pulling data from other systems. I don’t see the streams and pipes model fitting too well in this context (but maybe it is just my imagination which is limited).

Does this mean that node.js should be ruled out for back-end systems and that I am just plain wrong because I’m trying to use it in areas where it does not fit? I don’t think so. Back-end systems pull data. This means I/O. And the best way to do I/O is the asynchronous way. So why not node.js?

Moving Forwards

I wrote all this because I was getting really fed up with the childish attitude on the mailing list and the difficulty to get into interesting discussions.

As I said in the introduction, I’m a big fan of node.js. It is a great runtime and I’ll continue to use it.

I don’t agree with the gospel and I think that it is totally counterproductive.

The simple fact that the “callback hell” question comes back so regularly on the mailing list should raise a red flag. There is a reality behind this question and this reality cannot be ignored forever.

The gospel is counterproductive because it slows down the adoption of node. The current technical entry ticket is just too high. The core team is young and is probably used to working with high profile software developers. I am working with a mix of high profile and normal developers (people who have very valuable domain knowledge but are less savvy technically) and for them “JavaScript with callbacks” is just a no go.

There is a big opportunity for node.js to compete with PHP and the likes but it won’t succeed if it keeps the bar so high.

It is also counterproductive because people don’t use the tools that would allow them to develop 100% asynchronous modules without pain. So, what they end up doing instead is bury a few Sync calls in their modules, thinking that “well, this is just a little bit of file I/O; it won’t hurt” (I hit two cases like this recently and I had to fork and streamline them to eliminate the Sync calls).

And it is counterproductive because it pollutes the discussions, blurs the message and upsets everyone.

This entry was posted in Uncategorized. Bookmark the permalink.

42 Responses to Node.js: Awesome Runtime and New Age JavaScript Gospel

  1. Are the indented italicized sections blockquotes? If so, you should cite them. If they are not quotes, then you should clarify that you’re expressing your perception, which may or may not accurately reflect the reality of what others are attempting to communicate.

    Under “Every piece of software is not a proxy”, you write:

    they don’t push much data to other layers; instead, they respond to requests/questions by pulling data from other systems.

    Responding to requests by pulling data from other systems = proxy. That’s practically the definition of a proxy, in fact. Even a simple http pass-through proxy needs a knowledge of which other http server to send requests to, and must reformat the request to pass the headers properly.

    You mention “the core team”. The not-so-subtle (to those who know) implication you appear to be making is that your beef is primarily with Mikeal Rogers. I don’t think any node core committer ever said the things that you’re complaining about. Please be specific. Sideways allegations lead to more ill will than simply being direct.

    If I may be forgiven for paraphrasing Mikeal’s position in his recent blog post:

    1. You (and others) very noisily promote synchronous-looking flow-control libraries. (Streamline and fibers.)
    2. This promotion on every flow-control related thread can lead newcomers to draw the conclusion that these libraries are very widely used in the Node community.
    3. These libraries are not very widely used in the Node community. In fact, looking at actual usage, despite a year of aggressive promotion, they’re a vanishingly small minority.

    A design goal of Node is to not hide asynchronous behavior from the programmer. Yes, it is true, `module.doSomething(arg, cb)` is not *essentially* asynchronous. However, the “gentleman’s agreement” in designing callback APIs is that they must be either always-blocking or never-blocking. Given this, the pattern is more clear than `var result = module.doSomething(arg, _)`, which appears to return the result immediately. *That’s the **point** of streamline*, to make code read as if it’s synchronously blocking on each call, maintaining the call stack for try/throw/catch, and so on.

    When V8 delivers yield and generators, Node will not prevent them from functioning. Node is not a language design project. That’s why we don’t care about Streamline, and are not interested in ever incorporating anything like Streamline or Fibers into Node.js. We are designing the platform — we take the language as-is from V8.

    To follow my own advice regarding specificity:

    The idea that somehow there is a “gospel” or dogma being officially pushed by the Node.js project is simply insulting and incorrect. You’ve been around for a while. You should know better. I don’t care how you write your programs.

    The node core team is not under any illusions that our current APIs are perfect. Are you insane? Handling errors is nightmarishly error prone! Why do you think that we’re doing this whole domains feature for v0.8? It’s just that most of us think that Streamline is is the wrong solution to the wrong part of the problem, that’s all. You don’t get to call people dogmatic just because they don’t agree with you. That’s childish and rude, Bruno.

    There are almost 9000 packages on npm. 11 of those depend on streamline or are in some way related to it. The vast majority of programs written with Node use plain old JavaScript. Your claims about it being “too hard” are simply not validated by the evidence. I’ve written a few programs with Streamline. The learning curve is significant, and the build step is tedious. It is a different language, with different semantics, and yet it looks enough like JavaScript to be confusing.

    For a newcomer to JavaScript, perhaps it’s less significant of a learning curve than passing around lambdas, but the fact of the matter is that many people ARE familiar with JavaScript, and web browsers have been doing event-driven async IO for many years now.

    • tl;dr – You are complaining about the node core team oppressing your reasonable views with their unreasonable dogma, but actually, what you’re seeing is just regular node community members getting tired of you constantly telling them that what they’re doing is too hard, and promoting a library that they don’t like and almost no one uses.

    • Regarding the blockquotes, the sentence at the end (the worst is that this is hardly a caricature) is a rather obvious hint: I made them up.

      Regarding the back-end / proxy thing, these applications do not “just” pull data from other systems, they apply business rules in the middle.

      You’re just a liar when you say that you have written programs with streamline and that the learning curve is significant. If you had just tried streamline for 10 minutes you would know that the learning curve, especially for an experienced JavaScript programmer, is inexistant. If you know JavaScript and if you have written sync code before then you know how to write async code with streamline. It is as simple as this and this point is pure BS from your side (and I won’t take it).

      Sorry if I have misrepresented core team members other than Mikeal and you. You are the most vocal and I don’t really know what the others think. I should have been more specific.

      • these applications do not “just” pull data from other systems, they apply business rules in the middle.

        Deciding which server to proxy to isn’t a business rule? Munging headers isn’t a business rule?

        When Ryan said that “all programs are essentially proxies”, what he meant was that you’re receiving a request, and in response to that request, you’re fetching data from somewhere, then doing something to it, and returning it to the original caller. That’s what a non-trivial proxy does, and that’s exactly what you’re describing. If you pull data from a database, choose a template based on the url request, and then use the template to transform the data into html, that’s a fancy proxy.

        You’re just a liar

        That’s not a nice thing to say, Bruno.

        I’ve written nontrivial programs that do blocking IO in C, C++, PHP, Visual Basic, and multiple different JavaScript environments. I’ve also written nontrivial programs that do nonblocking IO in C and in JavaScript, on the server and in web browsers, and (via very convoluted machinations) even in PHP. Quite a few, in fact. I find streamline very difficult to read, and very difficult to write. It encourages a “single giant function” approach to problems, and it’s not clear (to me) what blocks and what goes to the event loop, or what the resulting code will look like.

        I used it for much more than 10 minutes before coming to this conclusion, in a few relatively filesystem programs, where I’m very familiar with the semantics of the problem: recursive folder removal, recursive mkdir, and walking a folder structure searching for a file of a given name. None of these are trivial programs, but all of them are easy and familiar enough to me that they were not introducing additional complexity to the equation. In all three cases, I found the streamline version significantly more difficult to understand than either the blocking sync version or the nonblocking callback-based async version. When my code was transformed, and I’d made a mistake, it was very difficult to tell what I’d actually done wrong, because the transformed code is so much more complicated than I would have written by hand.

        It’s possible I’m just not smart enough to grok streamline’s brilliance. But if that’s the case, and callbacks and events are pretty easy for me to follow, then why the “callbacks for dummies” line?

        Perhaps if you spent less time attacking people who disagree with you, and more time trying to understand their point of view, you’d be able to actually learn something that you could use to make streamline better.

      • The proxy topic is interesting. Yes, the back-end system “as a whole” can be seen as a very smart proxy. My point is more about the inside of that system. How are you going to write it? For me a check on an HTTP header is not a business rule, it is a technical rule; a business rule is something that deals with “business” concepts, for example a pricing rule like “if the item has been in stock for more than X weeks, discount it by Y %”. This require pulling data from some tables, with lazy loading and caching if possible. And you have lots of rules like this to evaluate, and sometimes complex dependencies between them. The guy who write these rules does not care whether the data is pulled in via synchronous or asynchronous I/O. What he cares is whether he can express his rules in a natural way or not, whether they will be easy to maintain or not, etc. If you tell him that he has to rethink his problem in terms of callbacks, streams and pipes, he will just think that you come from Mars.

        Regarding streamline programming, here is a little tip for people who start with filesystem calls:

        1. Write your code with Sync calls.
        2. Remove the Sync and add an _ parameter where the call expects a callback: data = fs.readFileSync(path) becomes data = fs.readFile(path, _)
        3. Add an _ parameter to all the functions that pass _ to other functions. Apply this process recursively until you hit the top level call
        4. You are done.

        So when you say that you “found the streamline version significantly more difficult to understand than either the blocking sync version or the nonblocking callback-based async version”, I find this very hard to believe because the streamline version is almost identical to the blocking sync version. To me, this is just BS and the fact that it is you (the leader of the node core team) who is saying this throws discredit on the tool that I have developed. Sure, newcomers to node won’t look at what I’m proposing if they get this kind of message from an authority like you. And I have to make a lot of noise on the forum to just tell them: be curious, take a look at the tools that are being proposed, don’t take all the FUD for granted.

        The comment about having to dive into the generated code just indicates that you don’t trust the streamline compiler. If something does not work as expected, post a repro case on streamline’s GitHub site. I’ll take a look and tell you if it comes from a misunderstanding of the language or from a compiler bug. Saying that you have to go into the generated code to understand what you did wrong is like saying that you have to go into the assembly generated by your C++ compiler to understand what you did wrong. People who develop with streamline don’t work like that.

        I would have preferred to leave this topic on the side but once more you’re spreading a negative message about streamline and I have to go into reactive mode. This has to stop!

        Part of my argument was about the non-technical aspects. Things like the difficulty to scale to large development teams, the difficulty to compete with PHP or RoR because of the need to rethink a lot things, the fact that people end up burying Sync calls in their modules, etc. I think that these aspects are important and that tools like streamline can help on the usability side. I’m not asking you to embark streamline into core or do anything like this, just to stop spreading negative messages about it.

        I’ll take an analogy with Linux: Linux is a great kernel. Linus Torvalds hates C++ but I don’t think that he tried to evangelize something like “Linux is C, you have to use C, not C++ to develop on Linux”. And C++ compilers (and lots of other compilers) contributed to the success of Linux.

        This is why I like to think of node.js as a runtime. The people who develop it may not like tools like streamline and they may have very good reasons to not use them (streamline has performance tradeoffs – I could make it faster by disabling features like the built-in long-stack-trace feature but I chose to favor usability and simplicity over pure performance). They should of course do their best to provide help around callback programming but spreading FUD on alternative solutions and telling people that they are not really doing node.js if they use these solutions is just counterproductive. My plea is that you treat node as a runtime that people will build upon with languages and tools of their choice, even if you don’t like some of them.

    • axkibe says:

      One point to note: Libraries !== Applications.

      I wouldn’t misinterpret the usage statistics just by counting node packages on Github. People are putting libraries there. Basically things other can use. For most Libraries it makes sense to stick to plain JS rather than pulling in another dependency the user might not like. Streamline excels well in developing heavily database based in-house applications, which code doesn’t make it to Github.

      What many discussions on the mailing list conclude with, our points of origin what solutions we are working with are vastly different, and many misunderstandings and arguments originate from missing that.

  2. mikealrogers says:

    @isaacs covered most of what I would normally cover but I would like to address one point I don’t think he covered enough.

    Callbacks are part of the design philosophy of node.js. To say that they aren’t is delusional. This is not the “opinion” of people “in core”. This is not a dogma that people who contribute to core made up after the fact, it’s a part of node.js, and it’s as fundamental to node.js as JavaScript is.

    The largest defenders of that philosophy will naturally be the people who believed it enough to contribute to core. You like fibers, that’s cool, go ahead and do that. node.js uses callbacks, that’s a fact, callbacks are part of it’s design philosophy, that’s a fact too. Alternative programming styles, like the one you prefer, are not part of that design philosophy, to claim it is would be like claiming that coffeescript is a part of the node.js design philosophy. In both cases, coffeescript and fibers, we aren’t going out of our way to break your library but you’ll never have the level of support that someone using the technologies we actually build node.js for (JavaScript and callbacks).

    It might make your argument sound better to frame it as *fibers* vs. *people who work on node core* but the truth is that it’s *fibers* vs. *node.js* and you’d just prefer that node.js mean something else.

    • Mikeal, I just have two comments:

      1) Streamline does not use fibers by default. There is a –fibers option but it is only an option. Standard and original streamline does not use any underlying C library at all and is actually fully “callback-oriented”: it transforms the code and generates callbacks. So this is not a *fibers* vs *people who work on node core* issue. This is a *some people who have developed solutions to the callback problem* vs *people who work on node core*

      2) Point taken. Node is not just a runtime. The gospel (you have to program with callbacks) is also part of node and you stick to your position. Does not change my viewpoint that this is counterproductive in many respects.

      • First of all: I love streamline and I use it for particularly hairy business logic code. I applaud to it for being as much JavaScript as possible and its a good temporary solution to fix the somewhat messy callbacks and tedious error handling.

        However, the fact that code is transformed means that its not V8 ECMAScript anymore. This is because V8 ECMAScript has no way to defer execution other than callbacks.

        Using a code transformation utility means that there is a language deficiency. This is probably true: there *is* a language deficiency with V8 ECMAScript, and it will be partially fixed with generators (yield) – the only thing that will remain a problem, I believe, is the call stack.

        Streamline also fixes this deficiency but introduces another language as a byproduct – a language extremely close to V8 JS but nevertheless different. Streamline has one particularly problematic difference: callback-based functions are not allowed to return values anymore. Its true that practically no callback code uses return values right now, but that may change in the future – and if streamline becomes extremely popular this change would be harder to happen, even though these return values could possibly become a nice mechanism for futures or perhaps error handling or whatever node core could come up with.

        I think you should really get involved in ECMAScript Harmony and help with making generators better (call stacks, shorter syntax etc). Although they involve a lot of yielding which may not be as short as streamline _ code, they will become standard soon and its best to have them be as good as possible. Streamline could then become a library – and as such be approved by everyone.

        The point is that code transformation = bad.

        You might say that language differences aren’t that important (especially small ones) The fact is that many languages with libraries which already have superior async I/O constructs, yet they’re nowhere near as popular as node.js.

        You might argue that a difference is minimal, yet isn’t it true that minimal differences belong in the language standardization effort as changes for the next version?

        I will continue using streamlinejs, but I really wish that V8 JS is fixed instead… and thats the whole point.

      • Hello @spion,

        Yes, streamline.js is a language of its own. It is currently implemented as a preprocessor but it could be directly implemented into JS engines. This would be much cleaner and it could allow interesting optimizations.

        I have been hesitant to get into ES-6 discussion so far because I get a feeling that it must be really hard to get to this level. But if people in the streamline community feel that this is worth it, I can try to engage with ES-6.

        The experiment that I did recently with generators (see my last post) shows that streamline can be easily implemented on top of generators but it also shows that generators introduce quite some overhead in the async flows. A native implementation of streamline would be much more efficient.

        I also find the preprocessor approach hacky but this was the easiest way to implement streamline easily and in a portable way. So maybe it is time to move.

    • axkibe says:

      Mikael, I’ve seen already on the list when we talked about coding examples that you do not understand streamline at all, neither its code nor the way it works. Yet you are the most focal about it evangelizing against it. I conside that combination pretty annoying.

      > The largest defenders of that philosophy will naturally be the people who believed it enough to contribute to core.

      “Philosophy”, “Believing” … are we doing engineering or religion here? Again I find it rather annoying the force you put on your philosophy you believe in. Other than you, I experienced the node community very practice oriented and pragmatic. If it works for someone…

  3. Tim Caswell says:

    Bruno, I’m sorry that your cool technology and active promotion of it has angered Mikeal, Isaac, and others.

    (warning this port is mainly about me and my experience, no real conclusion or argument)

    If it can help both sides gain understanding, I feel that I’m now in the middle. As many of you know, my role in the node community has been (off and on) helping newcomers get started and learn the ropes. When I first saw streamline, fibers, and other sync looking tools I thought they were hacks written to avoid learning proper JavaScript. I attacked them on the mailing list and encouraged newcomers to not use them because the trade-offs these tools provided were not worth it.

    Node had something called promises early on and we learned a very important lesson with them. Hiding the non-blocking nature of code is bad! It’s extremely important that whatever tool you use to ease the pain doesn’t hide the points that other code can be interleaved and mess with your state. Node “promises” had a method called “wait” that would just suspend the current stack and return the value after the promise was resolved. This was dangerous because libraries were using this technique and it meant that *any* function call could potentially cause your code to get suspended and have things change out from under you. Luckily Ryan has the sense to remove this feature quite quickly, but it left a bad taste in all our mouths ever since for things called “promises” and faux blocking.

    One day while fighting streamline and fibers, I realized these don’t have the same danger. Yes they are still faux blocking, but it’s not possible to hide it. You can always see somehow that an action may suspend your logic. This changed my opinion drastically. Instead of teaching newcomers to never use these tools, I simply advise them to learn the basics first and then once they are comfortable with that feel free to experiment with these alternative tools.

    Still, after years of writing node code (often as my day job, and often as a hobby), I never feel that using streamline, fibers, coffeescript, or even my own control-flow libraries should be used in my code. Why is this? Because I write libraries. I want my libraries to be as minimal as possible, especially in dependencies. I want the frames they insert into someone’s application stack to be as shallow as possible. I’m painfully aware of every little bit that adds bloat to someone’s app down the road. Software is complicated. I’d much rather take the time to hand-tune my callbacks (even if it means taking 2 hours to write a 30 line trampoline for a caching request) than use some abstraction.

    If I was writing a quick application that had a very tight deadline and limited resources, I would be much more likely to use coffeescript or streamline (assuming I didn’t mind the extra learning curve). The thing is I know JavaScript. I dream in callbacks. It’s actually easier for me to write vanilla javascript than acquire, learn, use, and debug some abstraction.

    I think streamline is a brilliant piece of engineering and I’m sure there are people who really benefit from such a tool. Just understand it’s not for everyone.

    • raynos2 says:

      > The thing is I know JavaScript. I dream in callbacks. It’s actually easier for me to write vanilla javascript than acquire, learn, use, and debug some abstraction.

      This, this a thousand times. Once you grok callbacks and “defeat callback hell”, it’s not that callbacks become easier, they are still ugly and messy, it’s that you understand them and can read them.

      It’s simply that callbacks are more readable then an abstraction and far easier to debug then an abstraction.

      This has the added benefit that 98% of the node code out there uses callbacks so I can read that too.

      If after all this you have a preference for streamline and want to use it in your own applications, go for it. You still need to understand callbacks so that you a) use them and b) read other people’s code. The exact same argument applies to CoffeeScript.

    • axkibe says:

      > Why is this? Because I write libraries.

      I think that sums it up pretty well. If you don’t write libraries but applications / (business) solutions that point my vary drastically.

    • Tim,

      This is a much more balanced view. I just have two comments to make:

      First, a technical precision about explicit yielding points. As you say, streamline enforces this strictly: all the yielding points are marked with an _, at all levels. So streamline enforces the same “single frame continuation” policy as harmony generators.

      The situation is a bit fuzzier with fibers. If you use the raw fibers API, you can hide a yielding point completely. But this is *not* the approach that Marcel has been advocating. Marcel has always stated that people should use the “futures” API that he has implemented on top of fibers. If you use this API strictly (this means having your own APIs return futures if they call wait), then yielding points will be explicit at all levels (the wait calls). This requires a bit of self-discipline but this is the recommended way. If you use streamline with the --fibers options, this discipline is enforced automatically.

      My second point is about your last sentence. I have never said that streamline was for everyone.

      I have said a few times that I was happy that the core team is writing to the bare metal with callbacks because speed is paramount at the core level. I have never asked for streamline to be incorporated into core in any way. The only thing I have suggested for inclusion into core is the “future == callback currying” API principle used by streamline: the idea that async functions would return a future if you omit the callback (f(a, b, cb) === f(a, b)(cb)) but I did not get any feedback on it. I have also proposed an alternative API for streams (async read and write with callbacks) but I got a strong setback from Mikeal. I have never asked for this stream API to be in core (I have a thin wrapper that implements it).

      Regarding library writers, I think that the kind of libraries that you describe (thin layers) are probably better without streamline (it removes a dependency and they will be a bit faster). I think that thicker libraries could benefit from streamline. For example, I recently used the pdfkit library; it is a pretty neat library but it needs to do a bit of file I/O (to load fonts and images) and it does it with Sync calls. To me, this is unacceptable. So I created my fork and streamlined it. I did the same thing with a zipping library. I think that an 100% async library written with a bit of streamline salt is much better than a library that hides Sync calls under the carpet.

      One last note on libraries: if you write a library with streamline, the async functions that you’ll be exposing are standard JavaScript functions with standard cb(err, result) node callbacks. So streamline is fully aligned on node’s API standards.

  4. aseemk says:

    Bruno, I long ago stopped worrying about what other people think. I’ve let my friends and peers routinely know how much I love Streamline because, unlike every other library/utility for reducing callback noise, it almost entirely *eliminates* noise altogether. And it’s just so damn elegant.

    But I’ve also let my friends and peers routinely know how much I love CoffeeScript. Even though I always loved JS (and gained quite a bit of expertise in it), I very much appreciate how much more robust CoffeeScript’s generated JS is, and how much more productive I am when I don’t have to worry about that robustness myself. (This doesn’t even mention the amazingly useful features of CS like list comprehensions, the existential operator, object/array destructuring, splats, etc.)

    And it was when I saw this blub paradox [1] clearly in action with CoffeeScript that I realized there’s no way people will simply accept Streamline.

    I’ve actually come to really admire the way Jeremy Ashkenas, author of CoffeeScript, has always handled this. He doesn’t try to convince the Node.js team to help CoffeeScript; he doesn’t even really preach/evangelize that CoffeeScript is great; he just says he finds it useful and some other people might too.

    This fight is just not worth your energy or time. When you can have a reasonable discussion that’s not immersed in dogma with people you respect and admire, great. The internet and mailing lists doesn’t tend to foster such discussions.

    My two cents. Keep up the great work; I and many others (often silent) appreciate it.


    • Hi Aseem,

      Thanks. I did not know the blub paradox. Pretty insightful.

      The argument was painful but I feel that it has brought a bit of perspective. And things usually cool down with time. So, back to work!


  5. Carlos Serrano-Morales says:

    Well Bruno, you certainly have asked Node.js out (, up to the point to give her presents and piss the rest of the suitors off…
    I recognize your Jacobinian approach there 😉

    Seriously beautiful, Streamline. Kudos to you again.

    Although I still have a lot to learn about node.js… I did try to use it as a basis for one of the services my environment uses, but did not succeed to bring it down to a level of complexity I felt manageable. My experience is that in the end when you are building relatively complex services, cooperative reactive event loop based systems are not that much simpler to manage than more traditional pre-emptive threaded based systems. I know it’s another long discussion you touched on elsewhere, and I know there is a lot of blood spilled on this.

    And gosh, what a passionate community!

    • Hi Carlos,

      Interesting article. Yes, she is a fun girl. Light and sweet, and she does not make you wait! The talking was too noisy to my taste but that’s fixed now. So we get along really well. Things have been a bit tense with her family lately, as you can see. Let time do its thing ….

      I need to turn skype on some day. I’d like to know more about your node experience, and your other projects 🙂


  6. Pingback: Node.js: Links, News and Resources (11) « Angel ”Java” Lopez on Blog

  7. Pingback: Move Over Meteor: Derby Is The Other High Speed Node.js Framework In Town | TechCrunch

  8. Pingback: Move Over Meteor: Derby Is The Other High Speed Node.js Framework In Town | Farmington News | Farmington Local News

  9. Pingback: Move Over Meteor: Derby Is The Other High Speed Node.js Framework In Town | Redwing News

  10. Pingback: Move Over Meteor: Derby Is The Other High Speed Node.js Framework In Town | Mendota Heights News

  11. Pingback: Move Over Meteor: Derby Is The Other High Speed Node.js Framework In Town | Coon Rapids News | Coon Rapids Local News

  12. Pingback: Move Over Meteor: Derby Is The Other High Speed Node.js Framework In Town | Network9ja

  13. Pingback: Move Over Meteor: Derby Is The Other High Speed Node.js Framework In Town

  14. Pingback: Move Over Meteor: Derby Is The Other High Speed Node.js Framework In Town | Blog

  15. Pingback: Move Over Meteor: Derby Is The Other High Speed Node.js Fram

  16. Pingback: Move Over Meteor: Derby Is The Other High Speed Node.js Framework In Town | Startup Help

  17. Pingback: Move Over Meteor: Derby Is The Other High Speed Node.js Framework In Town | Gaster Tech Blog

  18. Pingback: Meteorの前にはDerbyがいた: サーバサイドJavaScriptフレームワークの競争が活況

  19. Pingback: Wordpress Themes » Blog Archive » Move Over Meteor: Derby Is The Other High Speed Node.js Framework In Town

  20. Pingback: Move Over Meteor: Derby Is The Other High Speed Node.js Framework In Town | Krantenkoppen Tech

  21. Pingback: » Move Over Meteor: Derby Is The Other High Speed Node.js Framework In Town Shouldbook – Web Initiatives, Social Media, Technology news

  22. Pingback: Move Over Meteor: Derby Is The Other High Speed Node.js Framework In Town | Avalio Blog

  23. Pingback: Move Over Meteor: Derby Is The Other High Speed Node.js Framework In Town - The Review Blog

  24. JeanHuguesRobert says:

    That was an interesting read. I came to it while digging for information on so called “callback hell” that I am kind of struggling with. Yes, another flow lib effort, you may want to have a look.

  25. Wes McClure says:

    Fantastic post! Explicit callbacks are an extremely LEAKY abstraction for handling asynchronous, non blocking execution. Streamline is an elegant way to hide this abstraction and get back to writing code that matters. It’s all about WHAT not HOW, at least in my world.

  26. Pingback: Easy node.js streams | Bruno's Ramblings

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s