Javascript TypeError:无法读取属性';最新时间戳';未定义的

Javascript TypeError:无法读取属性';最新时间戳';未定义的,javascript,Javascript,我发现了很多类似的问题,但我仍然不知道我的代码出了什么问题。似乎我无法读取回调函数中的全局变量值(URL):我想更新回调函数中的URL latestTimestamp值(err,articles)。以下是出错的代码: var urls=[ {"url": "http://www.economist.com/feeds/print-sections/77/business.xml", "latestTimestamp": new Number(0)}, {"url": "http:

我发现了很多类似的问题,但我仍然不知道我的代码出了什么问题。似乎我无法读取回调函数中的全局变量值(URL):我想更新回调函数中的URL latestTimestamp值(err,articles)。以下是出错的代码:

var urls=[
    {"url": "http://www.economist.com/feeds/print-sections/77/business.xml", "latestTimestamp": new Number(0)},
    {"url": "http://news.sky.com/feeds/rss/home.xml", "latestTimestamp": new Number(0)},
    ]; // Example RSS Feeds; 

// parse RssFeeds from given websites and write them into databse
function parseRssFeeds(collection){
    var feed = require('feed-read');  // require the feed-read module

    // loop through our list of RSS feed urls
    for (var j = 0; j < urls.length; j++)
    {
        console.log('Original url timestamp is: '+ urls[j].latestTimestamp.toString());

        // fetch rss feed for the url: 
        feed(urls[j], function(err, articles)
        {
            // loop through the list of articles returned
            for (var i = 0; i < articles.length; i++)
            {           
                var message = 
                    {"title": articles[i].title,
                     "link": articles[i].link,
                     "content": articles[i].content,
                     "published": articles[i].published.getTime()};

                collection.insert(message, {safe:true}, function(err, docs) {
                    if (err) {
                        console.log('Insert error: '+err);
                    }else{
                        console.log('This item timestamp is: '+ message.published);
                        // get the latest timestamp
                        if (message.published >urls[j].latestTimestamp) {
                            console.log('update timestamp to be: '+ message.published);
                            urls[j].latestTimestamp = message.published;
                        }   
                    }
                });// end collection insert         
            } //  end inner for loop
        }) // end call to feed method

    } // end urls for loop
}
var-url=[
{“url”:http://www.economist.com/feeds/print-sections/77/business.xml,“latestTimestamp”:新编号(0)},
{“url”:http://news.sky.com/feeds/rss/home.xml,“latestTimestamp”:新编号(0)},
]; // RSS提要示例;
//解析给定网站的RSSFeed并将其写入数据库
函数解析器种子(集合){
var feed=require('feed-read');//需要提要读取模块
//循环浏览我们的RSS提要URL列表
对于(var j=0;jurl[j].latestTimestamp){
log('updatetimestamp to:'+message.published');
URL[j].latestTimestamp=message.published;
}   
}
});//结束集合插入
}//结束内部循环
})//结束对feed方法的调用
}//结束循环的URL
}
谢谢你的帮助。错误是:

TypeError: Cannot read property 'latestTimestamp' of undefined
    at /Users/Laura/Documents/IBM/project/TestList/app.js:244:37
    at /Users/Laura/Documents/IBM/project/TestList/node_modules/mongodb/lib/mongodb/collection/core.js:123:9
    at /Users/Laura/Documents/IBM/project/TestList/node_modules/mongodb/lib/mongodb/db.js:1131:7
    at /Users/Laura/Documents/IBM/project/TestList/node_modules/mongodb/lib/mongodb/db.js:1847:9
    at Server.Base._callHandler (/Users/Laura/Documents/IBM/project/TestList/node_modules/mongodb/lib/mongodb/connection/base.js:445:41)
    at /Users/Laura/Documents/IBM/project/TestList/node_modules/mongodb/lib/mongodb/connection/server.js:478:18
    at MongoReply.parseBody (/Users/Laura/Documents/IBM/project/TestList/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js:68:5)
    at null.<anonymous> (/Users/Laura/Documents/IBM/project/TestList/node_modules/mongodb/lib/mongodb/connection/server.js:436:20)
    at emit (events.js:95:17)
    at null.<anonymous> (/Users/Laura/Documents/IBM/project/TestList/node_modules/mongodb/lib/mongodb/connection/connection_pool.js:201:13)
TypeError:无法读取未定义的属性“latestTimestamp”
at/Users/劳拉/Documents/IBM/project/TestList/app.js:244:37
at/Users/劳拉/Documents/IBM/project/TestList/node_modules/mongodb/lib/mongodb/collection/core.js:123:9
at/Users/劳拉/Documents/IBM/project/TestList/node_modules/mongodb/lib/mongodb/db.js:1131:7
at/Users/劳拉/Documents/IBM/project/TestList/node_modules/mongodb/lib/mongodb/db.js:1847:9
在Server.Base.\u callHandler(/Users/劳拉/Documents/IBM/project/TestList/node\u modules/mongodb/lib/mongodb/connection/Base.js:445:41)
at/Users/劳拉/Documents/IBM/project/TestList/node_modules/mongodb/lib/mongodb/connection/server.js:478:18
在MongoReply.parseBody(/Users/劳拉/Documents/IBM/project/TestList/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js:68:5)
在空。(/Users/劳拉/Documents/IBM/project/TestList/node_modules/mongodb/lib/mongodb/connection/server.js:436:20)
在发出时(events.js:95:17)
在空。(/Users/劳拉/Documents/IBM/project/TestList/node_modules/mongodb/lib/mongodb/connection/connection_pool.js:201:13)

这可能是一个重复的问题,但我会在这里给出一个答案,因为对于尚未理解基本问题的JavaScript程序员来说,所有重复问题之间的关系往往很难理解

有两种方法可以解决这个问题。一种方法是更改创建回调的方式。不要使用内联匿名函数:

    feed(urls[j], function(err, articles)
    {
        // loop through the list of articles returned
        // ...
您将创建另一个返回回调的函数。将URL传递给该函数,返回的函数将使用URL:

   function makeFeedResultHandler(url) {
     return function(err, articles) {
       // loop through the list of articles returned
       // ... code as before up to this line:
                    if (message.published > url.latestTimestamp) {
                        console.log('update timestamp to be: '+ message.published);
                        url.latestTimestamp = message.published;
                    }   
       // ... etc
     };
   }
然后你会这样称呼“feed”:

   feed(urls[j], makeFeedResultHandler(urls[j]));
关键的区别在于,传递给“feed”的每个函数都有自己的对象的私有副本(好吧,一个要挑剔的引用副本),来自“url”数组,因此它根本不需要引用变量“j”。这就是问题的症结所在:“j”由代码中的所有回调共享。调用回调时,“j”的值等于“url”数组的长度,因此
url[j]
未定义的

另一种方法是使用新的JavaScript实现中提供的
.forEach
方法。这种方法将彻底消除“j”:

  urls.forEach(function(url) {
    console.log('Original url timestamp is: '+ url.latestTimestamp.toString());

    // fetch rss feed for the url: 
    feed(url, function(err, articles)
    {
        // loop through the list of articles returned
        // ... code as previously, substituting "url" for "urls[j]" everywhere
    });
 });

同样,这确保发送到“feed”函数的每个回调都有其自己的“url”元素副本。

扩展@Pointy在您的帖子下评论中所说的内容:

您在MongoDB中使用的插入函数是异步的,但是您将回调视为同步的。在您的循环中基本上发生的是,在您点击collection.insert之前,一切都按计划进行。从这里开始,过程中断,基本上说“我要告诉mongo现在插入一条记录……最终我会期待一个响应。”同时,循环继续到下一个索引,不会同步地等待回调触发

当您启动回调时,您的循环已经完成,并且J不再表示索引,这就是为什么它没有定义。您还可能会使用当前方法获得与您计划的索引不同的索引


我建议重新设计您的循环,以支持节点的异步特性。很奇怪,有一个很棒的库叫做,它使这个过程非常简单。async.each()函数应该可以帮助您完成所要做的事情。

这是一个非常常见的问题的实例,它会困住JavaScript程序员,通常是以这种形式出现的—使用索引变量的循环,以及在循环中为异步函数设置回调的代码