关于javascript:node.js:如何将变量传递到异步回调?

Node.JS: How to pass variables to asynchronous callbacks?

本问题已经有最佳答案,请猛点这里访问。

我确信我的问题是基于对node.js中的异步编程缺乏理解,但这里是这样的。

例如:我有一个要爬行的链接列表。当每个异步请求返回时,我想知道它是用于哪个URL的。但是,可能是由于竞争条件的原因,每个请求返回时都将URL设置为列表中的最后一个值。

1
2
3
4
5
6
7
var links = ['http://google.com', 'http://yahoo.com'];
for (link in links) {
    var url = links[link];
    require('request')(url, function() {
        console.log(url);
    });
}

预期输出:

1
2
http://google.com
http://yahoo.com

实际产量:

1
2
http://yahoo.com
http://yahoo.com

所以我的问题是:

  • 如何将URL(按值)传递给回调函数?或
  • 链接HTTP请求以便按顺序运行的正确方法是什么?或
  • 我还缺什么?
  • PS:1。我不想要一个检查回调参数的解决方案,而是一种从上面了解变量的回调的一般方法。


    您的url变量的作用域不属于for循环,因为javascript只支持全局和函数作用域。因此,您需要为您的request调用创建一个函数作用域,以便通过使用immediate函数在循环的每次迭代中捕获url值:

    1
    2
    3
    4
    5
    6
    7
    8
    var links = ['http://google.com', 'http://yahoo.com'];
    for (link in links) {
        (function(url) {
            require('request')(url, function() {
                console.log(url);
            });
        })(links[link]);
    }

    顺便说一句,在循环中间嵌入一个require是不好的做法。它应该重新写为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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]);
    }


    看看这个博客。可以使用.bind()方法传递变量。在您的情况下,应该是这样的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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。

    我建议你吃点什么

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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));
    }