1
votes

Impossible de promettre la fonction basée sur le rappel

Je souhaite utiliser la bibliothèque astro-js où un appel typique dans leur docs ressemble à ceci:

const aztroJs = require("aztro-js");
const {promisify} = require('util');
const getAllHoroscopeAsync = promisify(aztroJs.getAllHoroscope);

async function handle() {
  let result, sign = 'libra';
  try {
    result = await getAllHoroscopeAsync(sign);
  }
  catch (err) {
    console.log(err);
  }
  console.log("Result: " + result);
}

Pour plusieurs raisons, j'aimerais l'utiliser en utilisant le style async / await et en tirant parti de try / catch. J'ai donc essayé de promisifier comme ceci:

const aztroJs = require("aztro-js");

//Get all horoscope i.e. today's, yesterday's and tomorrow's horoscope
aztroJs.getAllHoroscope(sign, function(res) {
   console.log(res);
});

Cependant, lorsque je consigne le résultat, il est indéfini. Je sais que l'appel a fonctionné car la bibliothèque enregistre automatiquement une réponse via console.log et je vois une réponse correcte dans les journaux.

Comment puis-je "attendre" cet appel? (même par d'autres moyens si celui-ci n'est pas "promisible")


4 commentaires

promisify attend un rappel où le premier argument est une / l'erreur.


a) assurez-vous d'obtenir le this contexte de la méthode correctement b) assurez-vous que la méthode est conforme à la convention nodeback.


const getAllHoroscopeAsync = promisify ((sign, cb) => {aztroJs.getAllHoroscope (sign, res => {cb (null, res);});}); devrait fonctionner.


votre code semble être ok .. Comment appelez-vous votre méthode de poignée?


3 Réponses :


1
votes

Vous pouvez changer votre getAllHoroscopeAsync en une fonction de promesse

Exemple:

const getAllHoroscopeAsync = (sign) => 
    new Promise(resolve => 
            aztroJs.getAllHoroscope(sign, (res) => resolve(res)));


0 commentaires

3
votes

util.promisify () s'attend à ce que la fonction de rappel accepte deux arguments, le premier est une erreur qui doit être null lorsqu'il n'y a pas d'erreur et non nulle quand il y a une erreur et la seconde est la valeur (si aucune erreur). Cela ne promettra correctement une fonction que si le rappel suit cette règle spécifique.

Pour contourner ce problème, vous devrez promettre manuellement votre fonction.

// manually promisify
aztroJs.getAllHoroscopePromise = function(sign) {
    return new Promise(resolve => {
        aztroJs.getAllHoroscope(sign, function(data) {
            resolve(data);
        });
    });
};

// usage
aztroJs.getAllHoroscopePromise(sign).then(results => {
    console.log(results);
});

Remarque, c'est inhabituel pour une fonction asynchrone qui renvoie des données de ne pas avoir de moyen de renvoyer des erreurs, donc l'interface aztroJs.getAllHoroscope () semble un peu suspecte à cet égard.

En fait, si vous regardez le code pour cette fonction , vous pouvez voir qu'il fait une requête réseau en utilisant la bibliothèque request () , puis en essayant de lancer dans le rappel asynchrone en cas d'erreur. C'est une conception complètement imparfaite puisque vous (en tant qu'appelant) ne pouvez pas attraper les exceptions lancées de manière asynchrone. Donc, ce paquet n'a aucun moyen raisonnable de communiquer les erreurs de retour. Il est mal conçu.


0 commentaires

1
votes

Essayez la fonction personnalisée promise

aztroJs.getAllHoroscope[util.promisify.custom] = (sign) => {
  return new Promise((resolve, reject) => {
    aztroJs.getAllHoroscope(sign, resolve);
  });
};

const getAllHoroscopeAsync = util.promisify(aztroJs.getAllHoroscope);


0 commentaires