Je suis sûr que mon problème est basé sur un manque de compréhension de la programmation asynchrone dans node.js, mais voilà.
Par exemple: J'ai une liste de liens que je veux explorer. Lorsque chaque demande asynchrone revient, je veux savoir à quelle URL elle est destinée. Mais, probablement en raison des conditions de concurrence, chaque demande revient avec l'URL définie sur la dernière valeur de la liste.
var links = ['http://google.com', 'http://yahoo.com'];
for (link in links) {
var url = links[link];
require('request')(url, function() {
console.log(url);
});
}
Production attendue:
http://google.com
http://yahoo.com
Sortie réelle:
http://yahoo.com
http://yahoo.com
Ma question est donc soit:
PS: Pour 1. Je ne veux pas d'une solution qui examine les paramètres du rappel, mais une façon générale de rappeler les variables "d'en haut".
Votre variable url
n'est pas étendue à la boucle for
car JavaScript ne prend en charge que l'étendue globale et la fonction. Vous devez donc créer une étendue de fonction pour votre appel request
pour capturer la valeur url
à chaque itération de la boucle en utilisant une fonction immédiate:
var links = ['http://google.com', 'http://yahoo.com'];
for (link in links) {
(function(url) {
require('request')(url, function() {
console.log(url);
});
})(links[link]);
}
BTW, incorporer un require
au milieu de la boucle n'est pas une bonne pratique. Il devrait probablement être réécrit comme suit:
var request = require('request');
var links = ['http://google.com', 'http://yahoo.com'];
for (link in links) {
(function(url) {
request(url, function() {
console.log(url);
});
})(links[link]);
}
Vérifiez cela blog out. Une variable peut être passée en utilisant la méthode .bind (). Dans votre cas, ce serait comme ceci:
var links = ['http://google.com', 'http://yahoo.com'];
for (link in links) {
var url = links[link];
require('request')(url, function() {
console.log(this.urlAsy);
}.bind({urlAsy:url}));
}
Voir https://stackoverflow.com/a/11747331/243639 pour une discussion générale sur ce problème.
Je suggérerais quelque chose comme
var links = ['http://google.com', 'http://yahoo.com'];
function createCallback(_url) {
return function() {
console.log(_url);
}
};
for (link in links) {
var url = links[link];
require('request')(url, createCallback(url));
}