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")
3 Réponses :
Vous pouvez changer votre getAllHoroscopeAsync en une fonction de promesse
Exemple:
const getAllHoroscopeAsync = (sign) => new Promise(resolve => aztroJs.getAllHoroscope(sign, (res) => resolve(res)));
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.
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);
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?