web-dev-qa-db-ja.com

NodeJSが非同期の戻り値を取得(コールバック)

コールバックについてはインターネットでいろいろ読んでいますが、私の場合は理解できません。

この機能があり、実行時にコンソールにログを記録します。ただし、別の機能でこの応答が必要になったため、そのために苦労しています。

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

私はコールバックに頭を包むのに本当に苦労し、私はここで盲目です。

17
Havnar

コールバックは、返されるコードがすでに実行されているため、値を返すことはできません。

そのため、いくつかのことができます。 1つはコールバック関数を渡し、非同期関数がデータを取得したらコールバックを呼び出してデータを渡します。または、応答オブジェクトを渡し、非同期関数で使用します

コールバックを渡す

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);
    });
};
24
Patrick Evans

非同期の世界では、値を返すことはできません。値の準備ができたときに実行する必要があるものはすべて、コールバック内で実行する必要があります。別の選択肢は、promiseを使用することです。 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);
      }
    });
  });
};

これで、promiseを使用して、解決後に実行されるコールバックを渡すことができます。

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