4
\$\begingroup\$

I am writing non-blocking code as it should be in Node.JS. If I want run function A after B I do it using callback.

But I find this style guide:

Use closures, but don't nest them. Otherwise your code will become a mess.

Right:

setTimeout(function() {
  client.connect(afterConnect);
}, 1000);

function afterConnect() {
  console.log('winning');
}

Wrong:

setTimeout(function() {
  client.connect(function() {
    console.log('losing');
  });
}, 1000);

How deep should my closures be? Specifically, I'd like to consider this sample:

exports.profileImage = function(req, res) {
    var id = req.params.user_id;
    userProvider.get(id, function(err, user){
        if (err) throw err;
        userProvider.getImageById(user['image_id'], function(err, image) {
            if (err) throw err;
            userProvider.writeImageToDisk(image, function(err, path){
                if (err) throw err;
                res.sendfile(path);
            });
        });
    });
};
\$\endgroup\$
4
\$\begingroup\$

First of all, you are correct. One way to prevent deep nesting is to pull out the callback into it's own named function. This allows you to only be as deep as 2-3 levels in blocks of code.

function task1(){
  async1(task2);
}

function task2(){
  async1(task3);
}

function task3(){
  async1(task4);
}

Another way to do it is by using flow-control libraries which take advantage of the concept of Futures/Deferreds/Promises. There are a lot of ways to call them, but they are the same thing most of the time.

The basic concept is that they usually stack up callbacks via utility functions and then run them, depending on the result of the previous or depending on the used utility function. The code will look linear and synchronous, but it actually is running async and the library controls the flow of calls and results. In jQuery, you can do something like

//Run an addition in the server
$.get('add.php',{
    op1 : 1,
    op2 : 2
  })
  .then(function(result){
    //get the addition result (3) and multiply it on the server (another async)
    return $.get('multiply.php'{
      op1 : result,
      op2 : 3
    });
  })
  .then(function(result){
    //get the multiplication result (9) and divide it on the server (another async)
    return $.get('divide.php'{
      op1 : result,
      op2 : 9
    });
  })
  .done(function(result){
    console.log(result); //1
  });
\$\endgroup\$
2
\$\begingroup\$

as a personal preference I like the "Right" way that you have listed. it looks cleaner to me.

On the other hand I see lots of Java and JavaScript where they have nested functions that are not used anywhere else in the code, personally I don't like this, it looks way to complicated and if you want to use the inside function later on you have to rewrite it if it is nested inside of another function or use the outside function to use the inside function.

I would agree the "Right" example is the Right example.

Again, this is my personal preference.

\$\endgroup\$
  • 1
    \$\begingroup\$ I tend to agree with you, in general the 'arrow' design (you have multiple nests and the code shape resembles an arrowhead), is considered very bad practice; it can lead to missing brackets as well as scoping issues that are missed. \$\endgroup\$ – Evan Bechtol Apr 1 '16 at 20:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.