NodeJS get async return value (callback) [duplicat

2019-01-09 06:29发布

This question already has an answer here:

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.

2条回答
Lonely孤独者°
2楼-- · 2019-01-09 06:47

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);
};
查看更多
混吃等死
3楼-- · 2019-01-09 06:53

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);
    });
};
查看更多
登录 后发表回答