我正在编写一个脚本,该脚本读取多个twitter feed并将它们写入div。当我仅向特定的提要发出1个AJAX请求时,该代码有效,但是当我尝试遍历提要列表时,却一无所获。我敢肯定,这归咎于变量范围,但是我不知道如何用Javascript解决它。
这是有效的1-feed版本,略作简化(顺便使用jQuery):
function getTweets()
{
$.getJSON("http://api.twitter.com/1/statuses/user_timeline.json?screen_name=[my username]&count=10&include_rts=true&callback=?",
function(tweets){
var tweetArray = new Array();
$.each(tweets, function(i,item){
var tweet = item.text;
var htmlString = ...;
tweetArray.push(htmlString);
});
for(var i=0;i<tweetArray.length;i++)
{
$("#tweet-div").append(tweetArray[i]);
}
},"json");
}
因此,获取JSON数据,遍历其内容,将一些数据转换为HTML,然后将该HTML填充到数组中,然后遍历该数组,将其内容填充到我的DOM中。
这是我用来尝试读取多个提要(失败)的代码:
function getTweets()
{
var tweetArray = new Array();
var users = new Array();
var user1 = [twitter name];
var user2 = [twitter name]; //etc for each user
users.push(user1,user2,...);
for(var n=0;n<users.length;n++)
{
$.getJSON("http://api.twitter.com/1/statuses/user_timeline.json?screen_name="+users[n]+"&count=10&include_rts=true&callback=?",
function(tweets){
$.each(tweets, function(i,item){
var tweet = item.text;
var htmlString = ...;
tweetArray.push(htmlString);
});
},"json");
}//end main FOR loop
for(var i=0;i<tweetArray.length;i++)
{
$("#tweet-div").append(tweetArray[i]);
}
}
代码2的最大不同是,我将tweetArray从.getJSON成功函数的一侧移到了它的外部。似乎正在发生的事情是,当我在结尾的.append()部分中遍历tweetArray时,tweetArray中没有任何内容。
我猜对了吗,因为成功的.getJSON函数是一个单独的函数,它无法从我的getTweets()函数访问局部变量tweetArray吗?
如果是这样,如何解决此问题,同时仍能像我在#2中尝试的那样遍历用户列表?
抱歉,我在此处粘贴的代码中是否有任何错别字,但这里的语法错误不是问题,因为在我的网站#1上运行得很好。
更新:我意识到,如果在尝试将tweetArray数据追加到DOM之前将alert(tweetArray)插入代码中,它甚至不需要将tweetArray设置为全局变量即可工作。现在,我对发生的事情一无所知。
更新:这是我正在使用的实际代码的副本/粘贴:
function getTweets()
{
//retrieves a JSON file from twitter.com with the information specified in the URL
//parameters. A description of parameters can be found at
//https://dev.twitter.com/docs/api/1/get/statuses/user_timeline
var tweetArray = new Array();//holds HTML-formatted tweets for everyone
var users = new Array();//holds all the user account info
var user1 = "[twitter name]";
var user2 = "[twitter name]";
var user3 = "[twitter name]";
var user4 = "[twitter name]";
var user5 = "[twitter name]";
var user6 = "[twitter name]";
var user7 = "[twitter name]";
var user8 = "[twitter name]";
users.push(user1,user2,user3,user4,user5,user6,user7,user8);
for(var n=0;n<users.length;n++)
{
$.getJSON("http://api.twitter.com/1/statuses/user_timeline.json?screen_name="+users[n]+"&count=10&include_rts=true&callback=?",
function(tweets){
$.each(tweets, function(i,item){
var tweetString;
//the names of the various data can be found
//in the twitter API reference pages, such as
//https://dev.twitter.com/docs/api/1/get/statuses/user_timeline
var tweetText = '<div class="tweet-text" id="tweet-text'+i+'" >'+item.text+'</div>';
var userID = item.user.id_str;
var userName = '<div class="tweet-user-name" id="tweet-user-name'+i+'" >'+item.user.name+'</div>';
var userPic = '<img class="tweet-img" id="tweet-img'+i+'" src="'+item.user.profile_image_url +'" />';
//formats created_at data from twitter into a nice date/time
var tweetDate = item.created_at;
var hourminute = tweetDate.substr(tweetDate.indexOf(":")-2,5);
var hour = parseInt(hourminute.substr(0,2))+7;//the +7 is a time zone correction
if (hour > 12)
{
hour = hour-12;
}
else if(hour == 0)
{
hour = 12;
}
var ampm = "AM";
if(hour>=12)
{
ampm = "PM";
}
var minute = hourminute.substr(3,2);
var day = tweetDate.substr(0,3)
var dateNum = tweetDate.substr(8,2);
var month = tweetDate.substr(4,3);
switch(month)
{
case "Jan":
month="01"
break;
case "Feb":
month="02"
break;
case "Mar":
month="03"
break;
case "Apr":
month="04"
break;
case "May":
month="05"
break;
case "Jun":
month="06"
break;
case "Jul":
month="07"
break;
case "Aug":
month="08"
break;
case "Sep":
month="09"
break;
case "Oct":
month="10"
break;
case "Nov":
month="11"
break;
case "Dec":
month="12"
break;
}
var year = tweetDate.substr(-4,4);
var dateFormatted = '<div class="tweet-date" id="tweet-date'+i+'" >'+day+' '+month+'.'+dateNum+'.'+year+' • ' + hour +':'+ minute +' '+ ampm+'</div>';
//reformats the date yet again so that tweets can be sorted chronologically
var sortableDate = month+dateNum+year;
//combines all tweet information into one string of HTML
tweetString = '<div class="tweet" id="tweet'+i+'">'+ dateFormatted+userName+tweetText + '</div>';
var tempArray = new Array();
tempArray=[sortableDate,tweetString];
//pushes formatted tweet HTML code into an array
tweetArray.push(tempArray);
});
},"json");
}
//at this point in the code, the user's browser is still waiting to receive
//the JSON files from twitter, and tweetArray has no data in it. The next line
//causes the code to break for a few seconds while the data is retrieved from
//twitter before trying to insert anything into the DOM
var waitForJSON = setTimeout(function(){insertTweets(tweetArray)},2000);
}
function insertTweets(content)
{
//sort tweets in tweetArray by date instead of by author
content = content.sort();
content = content.reverse();
//change or remove the "Loading Tweets" message
if(content == "")
{
$("#load-status").html("There was an error retreiving tweets.");
}
else
{
$("#load-status").empty();
}
//loops through tweetArray and inserts HTML code into page
for(var i=0;i<content.length;i++)
{
$("#tweet-box").append(content[i][1]);
}
//create patterned background effect for tweets
$(".tweet:odd").css("background-color","#f0f0f0");
$(".tweet:even").css("background-color","#dddddd");
}
最佳答案
我正朝着先前答案的相反方向前进。您不希望tweetArray是全局的。
首先,如果一无所获,那么您的代码中可能会出现语法错误,并且您需要找到它,因为多用户代码应该给您太多(重复的推文),而不是没有。由于这是伪代码,而不是您的真实代码,因此我们无法真正解决语法错误所在的位置。因为语法错误很可能出现在getJSON成功函数处理程序中,所以您可能不会直接在调试器中看到语法错误。要查看它在哪里,您将需要在回调的开始处放置一个断点,并逐步浏览它以了解它的作用所在,或者在您的回调中放入try / catch并在抛出异常时输出一些调试信息。
除了潜在的语法错误之外,我在第二段代码中看到的问题是,您正在所有成功处理程序之间共享tweetArray,但随后在每个成功处理程序中,您要遍历整个tweetArray并附加结果。这意味着第一个JSON调用将起作用,因为它将把初始tweet收集到数组中,然后将它们全部追加。第二个JSON调用将添加到同一数组,然后遍历整个数组并将它们全部追加。这将再次插入来自第一个呼叫的推文-不是您想要的。第三次呼叫将再次复制之前的所有推文。解决该问题部分的方法是将tweetArray放入成功函数内,这样您就只可以从该特定JSON调用中收集并插入tweet。
要使每条推文仅被附加一次,我认为您需要像这样更改它:
function getTweets()
{
var users = new Array();
var user1 = [twitter name];
var user2 = [twitter name]; //etc for each user
users.push(user1,user2,...);
for(var n=0;n<users.length;n++)
{
$.getJSON("http://api.twitter.com/1/statuses/user_timeline.json?screen_name="+users[n]+"&count=10&include_rts=true&callback=?",
function(tweets){
var thisUsersTweets = []; // initialize this locally and separately for each success handler
$.each(tweets, function(i,item){
var tweet = item.text;
var htmlString = ...;
thisUsersTweets.push(htmlString); // collect the tweets for this user only
});
for(var i=0;i<thisUsersTweets.length;i++)
{
$("#tweet-div").append(thisUsersTweets[i]); // append just this user's tweets
}
},"json"); // end of getJSON call
} // end main "for" loop
} // end of getTweets()
如果您需要将整个tweet列表收集到一个数组中以供以后在函数中使用,那么您也可以这样做,但是由于您没有要求,因此我的示例不这样做。
既然您已经发布了实际的代码,并且我看到要在收集所有推文之后对它们进行排序,那么这是在实际代码中进行操作的一种方法。在此版本中,我们将统计您已发起多少个tweet请求,以及在收到所有响应后,我们将其称为insertTweets。
我已经将您的实际代码修改为此处的代码。只有四处更改:
在函数的顶层添加一个
responsesRemaining
变量删除超时呼叫
在每个JSON调用之前增加
responsesRemaining
变量在成功处理程序的末尾,递减
responsesRemaining
变量,如果它降至零(收到所有响应),则调用insertTweets()
。与setTimeout版本相比,此版本的代码具有以下优点:
无论鸣叫响应的时间如何,它都将起作用。
它将立即插入所有推文,而无需等待一定时间,因此可以更快地显示结果。
如果任何获取推文的请求花费更长的时间才能成功,则此方法仍会显示其推文(您不会)。
这是修改后的代码:
function getTweets()
{
//retrieves a JSON file from twitter.com with the information specified in the URL
//parameters. A description of parameters can be found at
//https://dev.twitter.com/docs/api/1/get/statuses/user_timeline
var tweetArray = new Array();//holds HTML-formatted tweets for everyone
var responsesRemaining = 0;
var users = new Array();//holds all the user account info
var user1 = "[twitter name]";
var user2 = "[twitter name]";
var user3 = "[twitter name]";
var user4 = "[twitter name]";
var user5 = "[twitter name]";
var user6 = "[twitter name]";
var user7 = "[twitter name]";
var user8 = "[twitter name]";
users.push(user1,user2,user3,user4,user5,user6,user7,user8);
for(var n=0;n<users.length;n++)
{
++responsesRemaining;
$.getJSON("http://api.twitter.com/1/statuses/user_timeline.json?screen_name="+users[n]+"&count=10&include_rts=true&callback=?",
function(tweets){
$.each(tweets, function(i,item){
var tweetString;
//the names of the various data can be found
//in the twitter API reference pages, such as
//https://dev.twitter.com/docs/api/1/get/statuses/user_timeline
var tweetText = '<div class="tweet-text" id="tweet-text'+i+'" >'+item.text+'</div>';
var userID = item.user.id_str;
var userName = '<div class="tweet-user-name" id="tweet-user-name'+i+'" >'+item.user.name+'</div>';
var userPic = '<img class="tweet-img" id="tweet-img'+i+'" src="'+item.user.profile_image_url +'" />';
//formats created_at data from twitter into a nice date/time
var tweetDate = item.created_at;
var hourminute = tweetDate.substr(tweetDate.indexOf(":")-2,5);
var hour = parseInt(hourminute.substr(0,2))+7;//the +7 is a time zone correction
if (hour > 12)
{
hour = hour-12;
}
else if(hour == 0)
{
hour = 12;
}
var ampm = "AM";
if(hour>=12)
{
ampm = "PM";
}
var minute = hourminute.substr(3,2);
var day = tweetDate.substr(0,3)
var dateNum = tweetDate.substr(8,2);
var month = tweetDate.substr(4,3);
switch(month)
{
case "Jan":
month="01"
break;
case "Feb":
month="02"
break;
case "Mar":
month="03"
break;
case "Apr":
month="04"
break;
case "May":
month="05"
break;
case "Jun":
month="06"
break;
case "Jul":
month="07"
break;
case "Aug":
month="08"
break;
case "Sep":
month="09"
break;
case "Oct":
month="10"
break;
case "Nov":
month="11"
break;
case "Dec":
month="12"
break;
}
var year = tweetDate.substr(-4,4);
var dateFormatted = '<div class="tweet-date" id="tweet-date'+i+'" >'+day+' '+month+'.'+dateNum+'.'+year+' • ' + hour +':'+ minute +' '+ ampm+'</div>';
//reformats the date yet again so that tweets can be sorted chronologically
var sortableDate = month+dateNum+year;
//combines all tweet information into one string of HTML
tweetString = '<div class="tweet" id="tweet'+i+'">'+ dateFormatted+userName+tweetText + '</div>';
var tempArray = new Array();
tempArray=[sortableDate,tweetString];
//pushes formatted tweet HTML code into an array
tweetArray.push(tempArray);
});
--responsesRemaining;
if (responsesRemaining <= 0) {
insertTweets(tweetArray);
}
},"json");
}
}
function insertTweets(content)
{
//sort tweets in tweetArray by date instead of by author
content = content.sort();
content = content.reverse();
//change or remove the "Loading Tweets" message
if(content == "")
{
$("#load-status").html("There was an error retreiving tweets.");
}
else
{
$("#load-status").empty();
}
//loops through tweetArray and inserts HTML code into page
for(var i=0;i<content.length;i++)
{
$("#tweet-box").append(content[i][1]);
}
//create patterned background effect for tweets
$(".tweet:odd").css("background-color","#f0f0f0");
$(".tweet:even").css("background-color","#dddddd");
}