user192936
user192936

Reputation:

Keeping variable value while making async call to FB.api

I am trying to get albums of a user with the following JavaScript function, first call gets album list, and while iterating in albums I get their cover picture:

function GetAlbums() {
    FB.api('/me/albums', function(resp) {
        var ul = document.getElementById('albums');
        for (var i=0, l=resp.data.length; i<l; i++) {
            var album = resp.data[i];
            FB.api('/'+album.cover_photo, function(resp1) {
                li = document.createElement('li'),
                a = document.createElement('a');
                a.innerHTML = "<img src='"+resp1.picture+"'/>"+album.name;
                a.href = album.link;
                li.appendChild(a);
                ul.appendChild(li);
                });
        }
    });
};

I don't know why but cover pictures are fetched ok, but album name is always same. Probably the inner FB.api call is async. and before it finishes the album iteration goes to the last element. How can I correct the code?

Upvotes: 0

Views: 604

Answers (1)

ori
ori

Reputation: 7847

Your problem has to do with Javascript closures.

The innermost function gets triggered N times, but the invocations are executed after GetAlbums has finished, and the album variable equals the last album, in each of the N executions.

A quick fix would be to move FB.api('/'+album.cover_photo... into a separate function:

function getAlbum(album) {
        FB.api('/'+album.cover_photo, function(resp1) {
            li = document.createElement('li'),
            a = document.createElement('a');
            a.innerHTML = "<img src='"+resp1.picture+"'/>"+album.name;
            a.href = album.link;
            li.appendChild(a);
            ul.appendChild(li);
            });
}

function GetAlbums() {
    FB.api('/me/albums', function(resp) {
        var ul = document.getElementById('albums');
        for (var i=0, l=resp.data.length; i<l; i++) {
            getAlbum(resp.data[i]);
        }
    });
};

The argument to getAlbum is now available to the inner function, and doesn't change.

Upvotes: 1

Related Questions