node.js - Any established convenient callback writing styles for javascript? - Stack Overflow

Callbacks are more and more a requirement in coding, especially when you think about Node.JS non-blocki

Callbacks are more and more a requirement in coding, especially when you think about Node.JS non-blocking style of working. But writing a lot of coroutine callbacks quickly bees difficult to read back.

For example, imagine something like this Pyramid Of Doom:

// This asynchronous coding style is really annoying. Anyone invented a better way yet?
// Count, remove, re-count (verify) and log.
col.count(quertFilter,          function(err, countFiltered) {
    col.count(queryCached,      function(err, countCached) {
        col.remove(query,       function(err) {
            col.count(queryAll, function(err, countTotal) {
                util.log(util.format('MongoDB cleanup: %d filtered and %d cached records removed. %d last-minute records left.', countFiltered, countCached, countTotal));
            });
        });
    });
});

is something we see often and can easily bee more plex.

When every function is at least a couple of lines longer, it starts to bee feasible to separate the functions:

// Imagine something more plex

function mary(data, pictures) {
    // Do something drastic
}

// I want to do mary(), but I need to write how before actually starting.

function nana(callback, cbFinal) {
    // Get stuff from database or something
    callback(nene, cbFinal, data);
}

function nene(callback, cbFinal, data) {
    // Do stuff with data
    callback(nini, cbFinal, data);
}

function nini(callback, data) {
    // Look up pictures of Jeff Atwood
    callback(data, pictures);
}

// I start here, so this story doesn't read like a book even if it's quite straightforward.

nana(nene, mary);

But there is a lot of passing vars around happening all the time. With other functions written in between, this bees hard to read. The functions itself might be too insignificant on their own to justify giving them their own file.

Callbacks are more and more a requirement in coding, especially when you think about Node.JS non-blocking style of working. But writing a lot of coroutine callbacks quickly bees difficult to read back.

For example, imagine something like this Pyramid Of Doom:

// This asynchronous coding style is really annoying. Anyone invented a better way yet?
// Count, remove, re-count (verify) and log.
col.count(quertFilter,          function(err, countFiltered) {
    col.count(queryCached,      function(err, countCached) {
        col.remove(query,       function(err) {
            col.count(queryAll, function(err, countTotal) {
                util.log(util.format('MongoDB cleanup: %d filtered and %d cached records removed. %d last-minute records left.', countFiltered, countCached, countTotal));
            });
        });
    });
});

is something we see often and can easily bee more plex.

When every function is at least a couple of lines longer, it starts to bee feasible to separate the functions:

// Imagine something more plex

function mary(data, pictures) {
    // Do something drastic
}

// I want to do mary(), but I need to write how before actually starting.

function nana(callback, cbFinal) {
    // Get stuff from database or something
    callback(nene, cbFinal, data);
}

function nene(callback, cbFinal, data) {
    // Do stuff with data
    callback(nini, cbFinal, data);
}

function nini(callback, data) {
    // Look up pictures of Jeff Atwood
    callback(data, pictures);
}

// I start here, so this story doesn't read like a book even if it's quite straightforward.

nana(nene, mary);

But there is a lot of passing vars around happening all the time. With other functions written in between, this bees hard to read. The functions itself might be too insignificant on their own to justify giving them their own file.

Share Improve this question edited Jan 10, 2013 at 13:43 Redsandro asked Jan 10, 2013 at 12:13 RedsandroRedsandro 11.4k15 gold badges80 silver badges111 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 6

Use an async flow control library like async. It provides a clean way to structure code that requires multiple async calls while maintaining whatever dependency is present between them (if any).

In your example, you'd do something like this:

async.series([
    function(callback) { col.count(queryFilter, callback); },
    function(callback) { col.count(queryCached, callback); },
    function(callback) { col.remove(query, callback); },
    function(callback) { col.count(queryAll, callback); }
], function (err, results) {
    if (!err) {
        util.log(util.format('MongoDB cleanup: %d filtered and %d cached records removed. %d last-minute records left.', 
            results[0], results[1], results[3]));
    }  
});

This would execute each of the functions in series; once the first one calls its callback the second one is invoked, and so on. But you can also use parallel or waterfall or whatever flow matches the flow you're looking for. I find it's much cleaner than using promises.

A different approach to callbacks are promises.

Example: jQuery Ajax. this one might look pretty familiar.

$.ajax({
  url: '/foo',
  success: function() {
      alert('bar');
  }  
});

But $.ajax also returns a promise.

var request = $.ajax({
  url: '/foo'
});

request.done(function() {
    alert('bar');
});

A benefit is, that you simulate synchronous behavior, because you can use the returned promise instead of providing a callback to $.ajax.success and a callback to the callback and a callback.... Another advantage is, that you can chain / aggregate promises, and have error handlers for one promise-aggregate if you like.

I found this article to be pretty useful. It describes the pro and cons of callbacks, promises and other techniques.

A popular implementation (used by e.g. AngularJS iirc) is Q.

Combined answers and articles. Please edit this answer and add libraries/examples/doc-urls in a straightforward fasion for everyone's benefit.

Documentation on Promises

  • Asynchronous Control Flow with Promises
  • jQuery deferreds

Asynchronous Libraries

  • async.js

    async.waterfall([
        function(){ // ... },
        function(){ // ... }
    ], callback);
    
  • node fibers

  • step

    Step(
        function func1() {
            // ...
            return value
        },
        function func2(err, value) {
            // ...
            return value
        },
        function funcFinal(err, value) {
            if (err) throw err;
        // ...
        }
    );
    
  • Q

    Q.fcall(func1)
        .then(func2)
        .then(func3)
        .then(funcSucces, funcError)
    
    • API reference
    • Mode examples
    • More documentation

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744938362a4602165.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信