2017-10-19 1 views
0

J'ai trois fichiers: user.js, influencer.js, & validate.jsComment transmettre des variables lors de l'utilisation de plusieurs exportations de modules dépendant du résultat d'un autre?

En user.js, j'importer ./influencer (comme var = influenceur) & ./validate (comme var = validate).

Ma fonction user.js:

addAccount: function(){ 
return functions.database.ref('/acct/{accountID}/name/').onCreate(event => { 
    var accountID = event.params.accountID; 
    var name = JSON.stringify(event.data.val()).replace(/['"]+/g, ''); 

    console.log("New Account Added ("+accountID+")"); 
    console.log("Nickname: " +name); 

    influencer.getIG(name); 

    var data = influencer.data; 

    validate.validateThis(data); 
}); 
} 

Avec influencer.getIG (nom), je passe le nom que nous avons défini ci-dessus à la fonction getIG (à l'intérieur de influencer.js). Cela fonctionne comme un charme. Le résultat est le corps JSON.

Ce que je veux faire maintenant est de prendre ce résultat de corps JSON et de le passer à la fonction de validation (dans validate.js). Dans influencer.js, j'ai également ajouté "exports.data = data;". Cela dit, je n'arrive pas à comprendre comment passer "data" à validate.js. Je l'enregistre, et il retourne indéfini. J'ai ajouté un timeout avant d'exécuter validateThis (data) et encore indéfini. La fonction de validation fonctionne très bien; Je l'ai testé. Mais clairement, je ne le fais pas de la bonne façon.

Ceci est ma fonction influencer.getIG:

module.exports = { 
getIG: function (name) { 
    var url = "https://www.instagram.com/"+name+"/?__a=1" 

    console.log(url); 

    request({ 
    url: url 
    }, function (error, response, body) { 

    var data = JSON.parse(body); 
    console.log(data); 
    exports.data = data; 
    }) 
} 
} 

Comment puis-je passer le résultat du second module au troisième module dans ma fonction? Qu'est-ce que je fais mal?

+0

Il semble que 'influencer.getIG()' soit asynchrone, ce qui signifie que vous avez besoin d'un rappel ou d'une promesse de savoir quand il est terminé avant de pouvoir accéder à 'influencer.data'. Pouvez-vous éditer votre question pour inclure du code pour 'influencer.getIG'? –

+0

est influencer.getIG (nom) asynchrone? si c'est le cas, data = influencer.data peut être appelé avant que les données réelles ne soient récupérées. Vous devrez peut-être utiliser le rappel ou la promesse si c'est le cas. –

+0

D'accord, je vais mettre à jour la question avec ces détails. J'ai cependant ajouté un gros timeout pour que influencer.getIG() soit fini avant de laisser valider validateThis (data). Il est toujours retourné indéfini, cependant. – ryangineer

Répondre

1

Vous pouvez essayer passer la fonction de rappel comme un autre paramètre à getIG

Votre fichier d'influence ressemblera à ceci.

module.exports = { 
    getIG: function (name, callback) { 
    var url = "https://www.instagram.com/"+name+"/?__a=1" 

    request({ 
     url: url 
    }, callback) 
    } 
} 

Et votre fichier utilisateur ressemblera à ceci

addAccount: function(){ 
    return functions.database.ref('/acct/{accountID}/name/').onCreate(event => { 
    var accountID = event.params.accountID; 
    var name = JSON.stringify(event.data.val()).replace(/['"]+/g, ''); 

    influencer.getIG(name, function (error, response, body) { 
     var data = JSON.parse(body); 
     validate.validateThis(data); 
    }); 
    }); 
} 

Utiliser le rappel veillera à ce que les données sont extraites avant de l'appeler.

+0

C'était parfait. Je ne suis pas tout à fait sûr pourquoi cela fonctionne comme il le fait exactement (je suis nouveau pour les rappels), mais c'est incroyable. Vous avez une parenthèse de fermeture supplémentaire sur la troisième à la dernière ligne de addAccount, mais sinon, cela fonctionne comme un charme. Je vous remercie! – ryangineer

+0

Merci @ryangineer Je vais essayer de l'expliquer du mieux que je peux. Tout d'abord, à partir de votre code lorsque vous obtenez IG sans rappel, javascript lancera immédiatement la commande suivante qui est var data = influencer.data; parce que javascript n'attend pas une opération asynchrone comme http arriver à la fin. À ce moment-là, les données ne sont pas arrivées et vous n'êtes pas défini. Cependant, un rappel sera appelé après qu'une opération asynchrone est terminée et que les données sont arrivées, vous êtes donc assuré de recevoir les données (le cas échéant). –

1

Comme l'ont noté les deux autres commentateurs - vous avez une fonction asynchrone avec un rappel. Une solution consiste à définir le rappel dans le fichier user.js et à le passer à la fonction getIG. Donc, vous auriez

user.js

<pre><code> 
addAccount: function(){ 
return functions.database.ref('/acct/{accountID}/name/').onCreate(event => { 
var accountID = event.params.accountID; 
var name = JSON.stringify(event.data.val()).replace(/['"]+/g, ''); 

console.log("New Account Added ("+accountID+")"); 
console.log("Nickname: " +name); 

function callback(err, res, data) { 
var data = JSON.parse(body); 
console.log(data); 
validate.validateThis(data) 
}  

influencer.getIG(name, callback); 
}); 
} 
</pre></code> 

puis dans l'autre fichier

influencer.js

module.exports = { 
getIG: function (name, callback) { 
var url = "https://www.instagram.com/"+name+"/?__a=1" 
request({ 
url: url 
}, callback) 
} 
} 

De cette façon la fonction asynchrone fonctionne à l'intérieur de l'influence r, puis rappelle à l'utilisateur lorsque le résultat est terminé. Les données sont maintenant dans la portée du fichier utilisateur à utiliser.

L'alternative (et meilleure) est d'utiliser des promesses. Dans ce cas, le code d'utilisateur serait le long des lignes de

influencer.getIg (nom) .alors (data => // utiliser les données ici dans user.js //)