私の問題はnode.jsの非同期プログラミングの理解不足に基づいていると確信していますが、ここに行きます。
たとえば、クロールするリンクのリストがあります。各非同期リクエストが返されるとき、どのURLが対象かを知りたいです。しかし、おそらく競合状態のために、各リクエストはリストの最後の値に設定されたURLで返されます。
var links = ['http://google.com', 'http://yahoo.com'];
for (link in links) {
var url = links[link];
require('request')(url, function() {
console.log(url);
});
}
期待される出力:
http://google.com
http://yahoo.com
実際の出力:
http://yahoo.com
http://yahoo.com
だから私の質問は次のいずれかです:
PS:1。コールバックのパラメーターを調べるソリューションではなく、「上から」の変数について知っているコールバックの一般的な方法が必要です。
JavaScriptはグローバルスコープと関数スコープのみをサポートするため、url
変数のスコープはfor
ループに限定されません。そのため、イミディエイト関数を使用して、ループの各反復でrequest
値をキャプチャするために、url
呼び出しの関数スコープを作成する必要があります。
var links = ['http://google.com', 'http://yahoo.com'];
for (link in links) {
(function(url) {
require('request')(url, function() {
console.log(url);
});
})(links[link]);
}
ところで、ループの途中にrequire
を埋め込むのは良い習慣ではありません。おそらく次のように書き直す必要があります。
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]);
}
これを確認してください blog out。変数は、.bind()メソッドを使用して渡すことができます。あなたの場合、次のようになります:
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}));
}
この問題の一般的な説明については、 https://stackoverflow.com/a/11747331/243639 を参照してください。
私は次のようなものを提案します
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));
}