我发现了很多类似的问题,但我仍然不知道我的代码有什么问题。似乎我无法在回调函数中读取全局变量值(urls):我想更新回调函数中的urls latestTimestamp值(错误,文章)。这是出错的代码:
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
}
感谢您的帮助。错误是:
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)
答案 0 :(得分:1)
这应该可以作为副本关闭,但我会在这里给出答案,因为所有重复问题之间的关系通常很难掌握,因为JavaScript程序员还没有理解基本问题。
有两种方法可以解决这个问题。一种方法是更改创建回调的方式。而不是使用内联匿名函数:
feed(urls[j], function(err, articles)
{
// loop through the list of articles returned
// ...
您要创建另一个返回回调的功能。您将该功能传递给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
};
}
然后你拨打#34; feed&#34;像这样:
feed(urls[j], makeFeedResultHandler(urls[j]));
关键的区别在于每个函数都传递给&#34; feed&#34;将从&#34; urls&#34;拥有自己的对象私有副本(以及引用的副本)。数组,所以它不需要引用变量&#34; j&#34;一点都不这就是问题的症结所在:&#34; j&#34;您的代码中的所有回调都是共享。在调用回调时,&#34; j&#34;的值。等于&#34; urls&#34;的长度。数组,因此urls[j]
为undefined
。
其他方法是使用.forEach
方法,可在较新的JavaScript实现中使用。这种方法将摆脱&#34; j&#34;共:
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
});
});
再一次,确保每个回调都发送到&#34; feed&#34;函数有自己的&#34; urls&#34;元件。
答案 1 :(得分:1)
扩展@Pointy在你发表的评论中所说的内容:
您与MongoDB一起使用的插入函数是异步的,但您正在将回调视为同步。你的循环中发生了什么,一切都按计划进行,直到你遇到collection.insert。从那里开始,这个过程就中断了,基本上就是说我现在要告诉mongo插入一条记录......最终我会期待一个回应。&#34;同时,循环继续到下一个索引,并且不会同步等待直到回调触发。
当您的回调触发时,您的循环已经完成,并且J不再代表索引,这就是它未定义的原因。您还冒着获得与此计划不同的索引的风险。
我建议您重新设计循环以支持节点的异步性质。有一个很棒的图书馆 - 奇怪的是 - async让这个过程变得非常简单。 async.each()函数可以帮助您完成您要完成的任务。