web-dev-qa-db-fra.com

NodeJS obtient la valeur de retour asynchrone (rappel)

J'ai lu sur Internet des rappels mais je ne peux tout simplement pas les comprendre dans mon cas.

J'ai cette fonction et elle se connecte à la console lorsqu'elle s'exécute. Cependant, j'ai maintenant besoin de cette réponse dans une autre fonction et j'ai du mal à le faire.

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

C'est là que je devrais l'obtenir: (Cela ne fonctionne évidemment pas car il n'attend pas la réponse.)

exports.getJobInfoByID = function(req, res) {

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

J'ai vraiment du mal à envelopper ma tête autour des rappels et je me regarde aveugle ici.

17
Havnar

Les rappels ne peuvent pas renvoyer une valeur car le code auquel ils retourneraient a déjà été exécuté.

Vous pouvez donc faire deux ou trois choses. Une passe une fonction de rappel et une fois que votre fonction asynchrone obtient les données, appelez le rappel et passez les données. Ou passez l'objet de réponse et utilisez-le dans votre fonction asynchrone

Passer un rappel

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

Passer un objet de réponse

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

Dans le monde asynchrone, vous ne pouvez pas retourner de valeurs. Tout ce qui doit être fait lorsque la valeur est prête doit être exécuté dans le rappel. Une autre alternative consiste à utiliser des promesses. Vous aurez besoin du es6-promise paquet:

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

Vous pouvez maintenant utiliser la promesse et transmettre les rappels qui s'exécuteront une fois qu'il sera résolu:

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

Ce qui précède peut être raccourci:

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