NodeJS получает возвращаемое значение async (обратный вызов)

Я читал в Интернете о обратных вызовах, но я просто не могу понять их в моем случае.

У меня есть эта функция, и она записывается в консоль при ее запуске. Однако мне теперь нужен этот ответ в другой функции, и я изо всех сил стараюсь это сделать.

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;
    });
};

Вот где я должен это получить: (Это явно не работает, потому что он не ждет ответа.)

exports.getJobInfoByID = function(req, res) {

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

Мне очень тяжело обволакивать обратные вызовы, и я смотрю на себя слепо.

Ответ 1

Обратные вызовы не могут вернуть значение, поскольку код, который они будут возвращать, уже выполнен.

Итак, вы можете сделать пару вещей. Один передаёт функцию обратного вызова, и как только ваша функция async получает вызов данных обратного вызова и передает данные. Или передать объект ответа и использовать его в вашей асинхронной функции

Передача обратного вызова

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);
    });
};

Передача объекта ответа

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);
    });
};

Ответ 2

В асинхронном мире вы не можете возвращать значения. Независимо от того, что необходимо сделать, когда значение будет готово, должно выполняться внутри обратного вызова. Другой вариант - использование promises. Вам понадобится пакет es6-promise:

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);
      }
    });
  });
};

Теперь вы можете использовать обещание и передавать обратные вызовы, которые будут выполняться после его разрешения:

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

Вышеуказанное может быть сокращено:

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