0

所以我用javascript写了这段代码:

// Additional initialization code such as adding Event Listeners goes here
            FB.api('593959083958735/albums', function(response) {
                if(!response || response.error) {
                    // render error
                    alert("Noo!!");
                } else {
                    // render photos
                    for(i=0; i<response.data.length; i++){
                        var albumName = response.data[i].name;
                        var albumCover = response.data[i].cover_photo;
                        var albumId = response.data[i].id;
                        console.log(albumName);
                        FB.api( albumCover, function(response) {
                            if(!response || response.error) {
                                // render error
                                alert("Noo!!");
                            } else {
                               // render photos
                               $("ul").append('<li>'+
                                    '<a href="testFile.HTML" data-transition="slidedown">'+
                                    '<img src= "' + response.picture + '"  />'+
                                     '<h2>' + albumName + '</h2>'+
                                     '<p> Test Paragraph</p>'+
                                     '</a>'+
                                     '</li>')
                                .listview('refresh');
                            }
                        });                                 
                    }
                }
            });

我正在使用 facebooks javascript API 将 facebook 页面的相册导入到我的 jquery 移动页面并将它们放在 listView 中。如您所见,我动态创建了 listView。listView 将专辑封面照片和标题作为缩略图,专辑名称。

然而,这里有一些可怕的错误。上面代码的结果可以在这里看到

缩略图都是正确的,但专辑名称是错误的。在每个单元格中,我都会得到最后一个专辑名称。如您所见,当我在代码中使用 console.log(albumName) 时,我得到了正确的所有名称。但在对 FB.api 的第二次调用中,该"albumName"变量仅包含最后一个专辑名称。

知道这里发生了什么吗?它真的让我发疯...

4

2 回答 2

2

看起来你有著名的 i for 循环问题,你只有对 i 的引用。

                for (var i = 0; i < response.data.length; i++) {  //added the var here
                    (function (i) {  //created a function
                        var albumName = response.data[i].name;
                        var albumCover = response.data[i].cover_photo;
                        var albumId = response.data[i].id;
                        console.log(albumName);
                        FB.api(albumCover, function (response) {
                            if (!response || response.error) {
                                // render error
                                alert("Noo!!");
                            } else {
                                // render photos
                                $("ul").append('<li>' +
                                    '<a href="testFile.HTML" data-transition="slidedown">' +
                                    '<img src= "' + response.picture + '"  />' +
                                    '<h2>' + albumName + '</h2>' +
                                    '<p> Test Paragraph</p>' +
                                    '</a>' +
                                    '</li>')
                                    .listview('refresh');
                            }
                        });
                    })(i);  //call the function with i
                }
于 2013-06-19T17:33:06.350 回答
2

这实际上不是i问题所在,而是albumName.

var大多数 JavaScript 引擎都非常宽容,允许您使用关键字多次声明同一个变量。这就是你在这里所做的。重要的for是要注意关键字不会引入新的范围;因此,当您(重新)声明循环(、、和)中的每个变量albumNamealbumCoveralbumId您将覆盖先前存储在同一变量中的值。

这会反过来咬你,因为你传递给的回调FB.api关闭了这些局部变量并且(显然)异步执行。到回调实际运行时,for循环已经完成,并且这些变量都设置为它们的最后一个值。

当然,例外是albumCover,正如您已经观察到的(您说缩略图都是正确的)。那是因为您将这个值FB.api同步传递给;即,你在循环中传递它,所以它不会被关闭。

要更好地理解 JavaScript 中的闭包,请参阅JavaScript 闭包如何工作?

要清楚:epascarello 的答案应该为您解决问题。将你的逻辑封装在一个匿名函数中确实会引入一个新的作用域(一个可以在各种场景中使用的有用技巧),因此albumName每个回调的关闭值等都是不同的。我只是想指出i问题本身并不是问题(因为您的回调根本没有结束i)。

于 2013-06-19T17:47:01.920 回答