开发者

Issue with creating HTML list (li) with call back function

I am facing this annoying issue with linking the right value to the right row in my HTML list which I am rendering, I think explaining my code would be the best way to explain so here I go.

I have a json string which return data about multiple players from a data base. The players may have multiple entries.

My string is of the form

jsonVar = {"someStr":[{"Fbid":"xx开发者_如何学Pythonxxxxxxx","score":"xxxxxx","game":"x","date":"1300689902"}, .... }]

now I want to display the data as a list on HTML for all the columns.

createList = function()
{
arrayLength = jsonVar.someStr.length;
for(i=0;i<arrayLength;i++)
{
    listName = document.id('name');
    listScore = document.id('score');
    listGameMode = document.id('gamemode');
    listTime = document.id('time');                             
    listfbID= document.id('fbID');

    fbId = jsonVar.someStr[i].Fbid;

    FB.api('/'+fbId+'/', function(response) 
    {   
         new Element('li',{text: response.first_name +" "+response.middle_name+" "+response.last_name }).inject(listName, 'bottom');        
    });
    new Element('li',{text:jsonVar.someStr[i].Fbid}).inject(listfbID, 'bottom');
    new Element('li',{text: jsonVar.someStr[i].score}).inject(listScore, 'bottom');
    new Element('li',{text:jsonVar.someStr[i].gamemode}).inject(listGameMode, 'bottom');
    new Element('li',{text: jsonVar.someStr[i].date}).inject(listTime, 'bottom');

    }
}   

The issue would be the name is not correctly returned with the rest of the entries on the list, this I am assuming is due to some delay with with returning of the name from fb.


You should create a closure so you can pass the current variable to the callback of the api call.

FB.api('/'+fbId+'/', ( function() {
    var current_i = i;
    return function(response) 
       {   
         new Element('li',{text: response.first_name +" "+response.middle_name+" "+response.last_name }).inject(listName, 'bottom');        
         new Element('li',{text:jsonVar.someStr[current_i].Fbid}).inject(listfbID, 'bottom');
         new Element('li',{text: jsonVar.someStr[current_i].score}).inject(listScore, 'bottom');
         new Element('li',{text:jsonVar.someStr[current_i].gamemode}).inject(listGameMode, 'bottom');
         new Element('li',{text: jsonVar.someStr[current_i].date}).inject(listTime, 'bottom');
       };
    })() );

generic example with closure and ajax callbacks at http://jsfiddle.net/gaby/zZ74b/


You mean UNIX time? Maybe you can use something like this?

var newDate = new Date();
newDate.setTime(unix*1000);
dateString = newDate.toUTCString();

Where unix is your time.


I think the problem arises because FB.api() makes an asynchronous XMLHttpRequest towards Facebook. The callback function you provide will be executed some time later, while your 'for' loop continues to run.

You cannot make FB.api() run synchronously, and you shouldn't do that as well, because it would slow down your list-building extremely, and it would make lots of requests towards Facebook.

IMHO an acceptable solution would be that you store those first, middle and last name fields in your own database, and pass it to the view with PHP.


For the lack of a better solution, this is what I do to solve the issue. I latch it to a unique ID on another column and insert the name by identifying the row. this solution works for me because my number of rows are very small. You may need to rethink the logic if you want to implement it on a larger scale.

createList = function() {
arrayLength = jsonVar.someStr.length;
for (i = 0; i < arrayLength; i++) {
    listName = document.id('name');
    listScore = document.id('score');
    listGameMode = document.id('gamemode');
    listTime = document.id('time');
    listfbID = document.id('fbID');

    fbId = jsonVar.someStr[i].Fbid;

    new Element('li', {
        text: jsonVar.someStr[i].Fbid
    }).inject(listfbID, 'bottom');
    new Element('li', {
        text: jsonVar.someStr[i].score
    }).inject(listScore, 'bottom');
    new Element('li', {
        text: jsonVar.someStr[i].gamemode
    }).inject(listGameMode, 'bottom');
    new Element('li', {
        text: jsonVar.someStr[i].date
    }).inject(listTime, 'bottom');
    new Element('li', {
        text: "loading"
    }).inject(listName, 'bottom');

    FB.api('/' + fbId + '/', function(response) {
        var connect;
        parent_id = $('fbID');
        child_id = parent_id.getElementsByTagName('li');

        for (j = 0; j < child_id.length; j++) {
            if (response.id == child_id[j].innerHTML) {
                parent_name = $('name');
                child_name = parent_name.getElementsByTagName('li');
                child_name[j].innerHTML = response.first_name + " " + response.middle_name + " " + response.last_name;
            }
        }
    });

}

}


Try This..

FB.api('/'+fbId+'/', function(response)
{       
    new Element('li',{text: response.first_name +" "+response.middle_name+" "+response.last_name }).inject(listName, 'bottom');
    new Element('li',{text:jsonVar.someStr[j].Fbid}).inject(listfbID, 'bottom');     
    new Element('li',{text: jsonVar.someStr[j].score}).inject(listScore, 'bottom');     
    new Element('li',{text:jsonVar.someStr[j].gamemode}).inject(listGameMode, 'bottom');     
    new Element('li',{text: jsonVar.someStr[j].date}).inject(listTime, 'bottom');   
    j++;          
});

But only if you're sure that the fb API will return the data in the order that you've called for it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜