1

这是在 Node.js爬虫上运行的简化代码,它获取所有数据。但是如何在“回调”中插入:var“i”的函数值from cycle for(var i=0... 当我添加name: datas[i].name时,它​​返回一个错误:

TypeError:无法读取未定义的属性“未定义”

var Crawler = require("crawler").Crawler;
var crawler = new Crawler;

var datas  = [
{name: 'John', url: 'john025'},
{name: 'Jim', url: 'jim04567'}
];

function crauler(done) {
for (var i = 0; i < datas.length; i++) {
    var link = 'http://somesite.com/' + datas[i].url;
    crawler.queue([{
        "uri": link,
            // inside this func
                        "callback": function (error, result, $, datas, i) {
            var arr = $('.blogpost').map(function (index) {
                var str = $(this).attr('href');
                var object = {
                    numb: str,
                    name: datas[i].name
                };
                return obj; 
            }).get().join(',');
            done(arr);
} }]) }; };

crauler (function (arr) {
console.log(arr);
});
4

3 回答 3

4

你不能像datas这样i传入回调函数。调用回调函数的参数取决于调用者,您无法控制它。

您会看到“TypeError: Cannot read property 'undefined' of undefined”,因为希望回调函数具有datasi作为参数;但是调用者将仅使用前 3 个参数调用回调[爬虫回调参考],所以datasandiundefined

因此,您应该从行中删除datasand i

"callback": function (error, result, $, datas, i) {

因为datas是定义在回调函数的外部作用域,所以回调可以访问datas而无需任何特殊处理。对于变量i,正如其他答案中提到的那样,它有点棘手,因此您需要为它创建一个闭包。

因此,您的回调函数定义应如下所示:

"callback": (function(i) { // create closure for i
    return function (error, result, $) { // no more datas and i here
        var arr = $('.blogpost').map(function (index) {
            var str = $(this).attr('href');
            var object = {
                numb: str,
                name: datas[i].name // access datas as it
            };
            return obj; 
        }).get().join(',');
        done(arr);
    }
})(i)
于 2013-06-23T16:14:02.297 回答
2

您需要一个闭包来捕获这些值,这是解决问题的一种方法。阅读闭包

Javascript

var Crawler = require("crawler").Crawler;
var crawler = new Crawler;

var datas = [{
    name: 'John',
    url: 'john025'
}, {
    name: 'Jim',
    url: 'jim04567'
}];

function queue(link, i) {
        crawler.queue([{
            "uri": link,
            // inside this func
            "callback": function (error, result, $, datas, i) {
                var arr = $('.blogpost').map(function (index) {
                    var str = $(this).attr('href');
                    var object = {
                        numb: str,
                        name: datas[i].name
                    };
                    return obj;
                }).get().join(',');
                done(arr);
            }
        }]);
}

function crauler(done) {
    for (var i = 0; i < datas.length; i++) {
        var link = 'http://somesite.com/' + datas[i].url;
        queue(link, i);
};

crauler(function (arr) {
    console.log(arr);
});
于 2013-06-23T15:56:28.800 回答
2

您正在尝试在i导致您出现问题的循环内部创建一个闭包。这个答案应该可以帮助你:

循环内的 JavaScript 闭包——简单实用的示例

于 2013-06-23T15:47:32.610 回答