how to browserify a node-js module?

How do I make my asynchronous code look readable/beautiful?

  • I'm looking at my nodejs projects code and it seems like the code is becoming very messy because of node's style of hooking functions to the callback. even if I try to split callbacks into separate functions it still looks a bit messy. I was wondering if any one created a module that allows writing code in a more organized/readable way.

  • Answer:

    There are many libraries out there that will help you make your asynchronous code more readable. All have different pros and cons, so your choice will depend on the project you have in mind. Also, you might need to consider which syntax makes the most sense to you, among all of these projects. Here are all the libraries that I have experimented with, so far: Async: https://github.com/caolan/async Step: https://github.com/creationix/step Seq: https://github.com/substack/node-seq Q: https://github.com/kriskowal/q Futures: https://github.com/coolaj86/futures Deferred: https://github.com/medikoo/deferred What is the core difference? On one side, Async, Step and Seq use a simple way to write asynchronous code and make it more readable. Q, Futures and Deffered, on the other side, use the promise pattern. And what is the promise pattern? When using the promise pattern, an asynchronous function will return a promise object. A promise object represents an eventual value. This means that this value may already be available or is expected to be available in the future. Also, a promise can succeed or fail. Hum... Can you show some demo code? Let's consider this piece of asynchronous code, which is not very readable: // Declaration asynchronous functions var stepA = function (cb) { setTimeout(cb.bind(null, 1), 500); }, stepB = stepC = function (v, cb) { setTimeout(cb.bind(null, v + 1), 500); }, stepD = function (v1, v2, cb) { setTimeout(cb.bind(null, v1 * v2), 500); }, finalStep = function () { console.log('All steps accomplished'); }; // End declaration stepA(function (valueA) { console.log('End step A'); stepB(valueA, function(valueB) { console.log('End step B'); // As we launch step C and step D in parallel // we setup an increment // to know when the 2 functions have completed var cpt = 0; stepC(valueB, function(valueC) { console.log('End step C'); cpt++; if (cpt === 2) { finalStep(); } }); stepD(valueA, valueB, function (valueD) { console.log('End step D'); cpt++; if (cpt === 2) { finalStep(); } }) }); }); Now let's see how it would be written with the promise pattern (Deferred library): // Deffered mode // Declaration asynchronous functions var stepA = function (cb) { setTimeout(cb.bind(null, 1), 500); }, stepB = stepC = function (v, cb) { setTimeout(cb.bind(null, v + 1), 500); }, stepD = function (v1, v2, cb) { setTimeout(cb.bind(null, v1 * v2), 500); }, finalStep = function () { console.log('All steps accomplished'); }; // End declaration var deferred = require('deferred'), _valueA = null; // Promisify the functions stepA = deferred.promisify(stepA); stepB = deferred.promisify(stepB); stepC = deferred.promisify(stepC); stepD = deferred.promisify(stepD); // Call step1 stepA() .then(function (valueA) { _valueA = valueA; console.log('End step A'); return stepB(valueA) }) .then(function (valueB) { console.log('End step B'); console.log('Call step C and step D'); // Return a promise wich is completed when the 2 promises are completed return deferred(stepC(valueB), stepD(_valueA, valueB)) }) .then(finalStep); Now with async library : // Declaration asynchronous functions // Change steps to specify at async there is no error (first argument) var stepA = function (cb) { setTimeout(cb.bind(null, null, 1), 500); }, stepB = stepC = function (v, cb) { setTimeout(cb.bind(null, null, v + 1), 500); }, stepD = function (v1, v2, cb) { setTimeout(cb.bind(null, null, v1 * v2), 500); }, finalStep = function () { console.log('All steps accomplished'); }; // End declaration var async = require('async'), _valueA = null; async.waterfall([ stepA, function (valueA, next) { console.log('End step A'); // Copy this variable to access on it on the next scope _valueA = valueA; stepB(valueA, next); }, function (valueB, next) { console.log('End step B'); async.parallel([ function (callback) { console.log('Call step C'); stepC(valueB, callback) }, function (callback) { console.log('Call step D'); stepD(_valueA, valueB, callback) } ], next) }, finalStep ]); Now you understand the two different ways to make your asynchronous code more readable. If you need further explanations, feel free to ask in the comments. Thanks to for pointing me to this question and the help on improving my english.

Sébastien Chopin at Quora Visit the source

Was this solution helpful to you?

Other answers

TL;DR: There are other ways to resume routines when they become available than callbacks. can be alternative one. CPS (continuation-passing style) basically makes code hard to read and write, in particular when it needs imperative features of programming language (e.g. continue, break, goto). When you do CPS, you have to reinvent most of control structures like  continue and break that should be implemented by programming language  implementations (compilers and interpreters). The alternative solution is using (or continuations) to resume followed routines when an idle socket gets available. You can casually use language features like continue and break with coroutines as you used to do. For example, the following CPS code: function getFollowers(screenName, complete, cursor) { var path = '/1/followers/ids.json?screen_name=' + screenName + '&cursor=' + (cursor || '-1'); http.get({ host: 'api.twitter.com', path: path }, function (res) { res.setEncoding('utf8'); var buffer = ''; res.on('data', function (chunk) { buffer += chunk; }) res.on('end', function () { var data = JSON.parse(buffer); if (data['next_cursor']) { getFollowers(screenName, function (d) { complete(data['ids'] + d); }, data['next_cursor_str']); } else { complete(data['ids']); } }); });}getFollowers('lily199iu', function (data) { console.log(data);}); can get simpler with coroutines: from gevent.monkey import patch_all; patch_all()import urllib2import jsondef get_followers(screen_name): url = 'http://api.twitter.com/1/followers/ids.json' \ '?screen_name={0}&cursor={1}' next_cursor = -1 ids = [] while next_cursor: u = urllib2.urlopen(url.format(screen_name, next_cursor)) data = json.load(u) for id_ in data['ids']: yield id_ next_cursor = data['next_cursor']print list(get_followers(screen_name='lily199iu')) If you want to use coroutines in node.js, try node-fibers (https://github.com/laverdet/node-fibers).

Hong Minhee ・ 洪 民憙

I recently wrote a book on this subject (http://leanpub.com/asyncjs), because it's probably the hottest topic in JavaScript today ("Semicolongate" aside). Sébastien's answer to this question is right on the mark: There are several flow control libraries (Async.js, the most popular, is covered in the book) and there's a design pattern called Promises that, though it's been around for decades, has only recently entered the mainstream programming lexicon. I like Promises so much that they get an entire chapter in the book, and I'll be speaking about them at FluentConf in May. Here's the bad news: The JS landscape is rapidly shifting. There is no "standard" control flow library, and there are several rival implementations of Promises. (Blame the jQuery team for ignoring the CommonJS spec and doing their own thing.) If you're using libraries that are callback-based, converting them to Promise-based code requires extra boilerplate—and vice versa. There's no silver bullet. And yet, I love JavaScript. The way that Node.js came out of nowhere in the last three years is an amazing triumph, and it's proven that JavaScript is a first-rate programming language with advantages beyond its monopoly over the browser. So my advice is: Learn what libraries and techniques people are using, and be creative about organizing your code. Above all else, resist the urge to nest callbacks within callbacks within callbacks. If you think carefully, you can always find another way.

Trevor Burnham

I think another option is try node v0.11.x version, but it's still unstable. from v0.11 nodejs start support https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function* , which will make a chance let you away from Callback pitfalls, vs promise or other patterns, Generators are javascript native: http://jlongster.com/A-Study-on-Solving-Callbacks-with-JavaScript-Generators

Weixiao Fan

I would also recommend the RxJS: http://go.microsoft.com/fwlink/?LinkID=182999 library from Microsoft. Erik Meijer is behind this project, which provide LINQ style combinators to work with asynchronous computation.  Here are some examples of usage I have put together over the last couple of months: http://tech.loku.com/tag/rxjs/

Roger Castillo

I like node-fiberize. It uses Fibers to keep your asynchronous code even cleaner than the previous examples: https://github.com/lm1/node-fiberize var fiberize = require('fiberize'); fiberize.start(function() { console.log('Hello'); fiberize.sleep(1000); console.log('World'); });

Ahmed Magdy

Check out the async library: https://github.com/caolan/async It provides all kinds of great flow-control methods to tame the callbacks.

Nicolas LaCasse

You can try to use http://maxtaco.github.com/coffee-script/ IcedCoffeeScript which introduced "await" and "defer" primitives to solve this problem.

Boris Staal

We use forward-declared functions, no libraries required: // Declaration asynchronous functions var stepA = function (cb) { setTimeout(cb.bind(null, 1), 500); }, stepB = stepC = function (v, cb) { setTimeout(cb.bind(null, v + 1), 500); }, stepD = function (v1, v2, cb) { setTimeout(cb.bind(null, v1 * v2), 500); }, finalStep = function () { console.log('All steps accomplished'); }; // End declaration stepA(functionA); function functionA(valueA) { console.log('End step A'); stepB(valueA, functionB); function functionB(valueB) { console.log('End step B'); // As we launch step C and step D in parallel // we setup an increment // to know when the 2 functions have completed var cpt = 0; stepC(valueB, functionC); function functionC(valueC) { console.log('End step C'); cpt++; if (cpt === 2) { finalStep(); } }; stepD(valueA, valueB, functionD); function functionD(valueD) { console.log('End step D'); cpt++; if (cpt === 2) { finalStep(); } }; }; };

Darren Hobbs

Related Q & A:

Just Added Q & A:

Find solution

For every problem there is a solution! Proved by Solucija.

  • Got an issue and looking for advice?

  • Ask Solucija to search every corner of the Web for help.

  • Get workable solutions and helpful tips in a moment.

Just ask Solucija about an issue you face and immediately get a list of ready solutions, answers and tips from other Internet users. We always provide the most suitable and complete answer to your question at the top, along with a few good alternatives below.