Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NodeJS get async return value (callback) [duplicate]

Tags:

I have read around the internet about callbacks but I just can't understand them in my case.

I have this function, and it logs to console when it runs. However I now need this response in another function and I am struggling to do so.

var asyncJobInfo = function(jobID, next) {

    var oozie = oozieNode.createClient({ config: config });

    var command = 'job/' + jobID + '?show=info';

    console.log("running oozie command: " + command);

    oozie.get(command, function(error, response) {

    console.log("*****response would dump to console here:*****");
//  console.log(response);
    return response;
    });
};

This is where I should get it: (This obviously doesn't work because it doesn't wait for the response.)

exports.getJobInfoByID = function(req, res) {

    var jobIDParam = req.params.id;
    res.send(asyncJobInfo(jobIDParam));
}

I really struggle to wrap my head around callbacks and I'm staring myself blind here.

like image 563
Havnar Avatar asked Aug 20 '14 08:08

Havnar


2 Answers

Callbacks can't return a value as the code they would be returning to has already executed.

So you can do a couple things. One pass a callback function and once your async function gets the data call the callback and pass the data. Or pass the response object and use it in your async function

Passing a callback

exports.getJobInfoByID = function(req, res) {
    var jobIDParam = req.params.id;
    asyncJobInfo(jobIDParam,null,function(data){
       res.send(data);
    });
}

var asyncJobInfo = function(jobID, next,callback) {
    //...
    oozie.get(command, function(error, response) {
       //do error check if ok do callback
       callback(response);
    });
};

Passing response object

exports.getJobInfoByID = function(req, res) {
    var jobIDParam = req.params.id;
    asyncJobInfo(jobIDParam,null,res);
}

var asyncJobInfo = function(jobID, next,res) {
    //...
    oozie.get(command, function(error, response) {
       //do error check if ok do send response
       res.send(response);
    });
};
like image 129
Patrick Evans Avatar answered Oct 06 '22 00:10

Patrick Evans


In async world you can't return values. Whatever needs to be done when the value is ready should be executed inside the callback. Another alternative is using promises. You'll need the es6-promise package:

var Promise = require('es6-promise').Promise;

var asyncJobInfo = function(jobID) {
  var oozie = oozieNode.createClient({config: config});
  var command = 'job/' + jobID + '?show=info';
  console.log("running oozie command: " + command);
  // Creates a new promise that wraps
  // your async code, and exposes two callbacks:
  // success, and fail.
  return new Promise(function(success, fail) {
    oozie.get(command, function(error, response) {
      if (error) {
        fail(error);
      } else {
        success(response);
      }
    });
  });
};

Now you can use the promise and pass the callbacks that will run once it is resolved:

exports.getJobInfoByID = function(req, res) {
  asyncJobInfo(req.params.id).then(function(data) {
    res.send(data)
  }).catch(function(error) {
    console.error(error);
  });
};

The above can be shortened:

exports.getJobInfoByID = function(req, res) {
  asyncJobInfo(req.params.id)
    .then(res.send.bind(res))
    .catch(console.error);
};
like image 37
elclanrs Avatar answered Oct 05 '22 23:10

elclanrs