0

In nodejs, a lot of function calls are implemented as non-blocking function. Sometimes there could be dependencies between these function calls. For example, when user login, I want first get the user type of the user and then according to the user type I can get the tasks which are just assigned this user type. In the non-blocking function, I use nested function call:

$http.post(url_login, login_request)
     .success(function(req) {
          $http.post(url_get_tasks, req.type)
               .success(function(req) {
                    //update tasks
               })
     })

A lot of libraries provides non-blocking functions only, for example, the node_redis library. Is there any good way to handle the nested non-blocking function calls to solve the dependency problem.

Ciel
  • 5,551
  • 5
  • 17
  • 24

2 Answers2

1

There is a page dedicated to this exact problem: http://callbackhell.com/

To sum up, you have the option

If I am not mistaken, you are using the Angular $http service, which should support proper promise chaining, so you could reduce your code to

$http.post(url_login, login_request)
    .then(function(req){
         return $http.pos(url_get_tasks, req.type);
    })
    .then(function(req){
         // update tasks
    })
    .catch(function(err){
         // errors from the first AND second call land here
    })

You can write a simple wrapper for async functions to turn them into promises:

 // this assumes standard node.js callbacks with the
 // signature (error, data)
 function toPromise(fn){
     return function() {
         var args = Array.prototype.slice.call(arguments);
         var scope = this;
         return new Promise(function(resolve, reject){
             var cb = function(err, data) {
                 return err ? reject(err) : resolve(data);
             };
             args.push(cb);
             fn.apply(scope, args);
         });
     };
  }

  // turn fs.readdir into a promise
  var readdir = toPromise(require('fs').readdir);
  readdir('.')
     .then(function(files){
         console.log(files);
     })
     .catch(function(err){
         console.log('reading files failed');
     }) 

There was another question regarding Angular $http promises which might help you understand them better: here

Community
  • 1
  • 1
lordvlad
  • 5,200
  • 1
  • 24
  • 44
0

I'm not 100% sure what you are asking, but if you want to reduce nesting in your code you can move the inner functions out like this:

function success1(req) {
    //update tasks
}
function success2(req) {
    $http.post(url_get_tasks, req.type).success(success1)
}

$http.post(url_login, login_request).success(success2)

obviously you should pick better names than success1 though

codebox
  • 19,927
  • 9
  • 63
  • 81