我在我的 jquery 移动网站 中使用 Facebooks Javascript API
,以便从 Facebook 公共(public)页面下载相册和照片并将其呈现到我的网站。
API 的工作方式非常简单,我让一切都变得相当容易。
到目前为止我所做的事情正在发挥作用
当用户点击按钮时,我加载一个页面,其中调用 javascript FB API 并动态生成特定 Facebook 页面的所有相册的列表,以及所有照片等。这非常有效。当调用 API 时,它仅获取 25 个专辑,而当我有更多专辑要获取时,我有一个“更多专辑”按钮,用户点击该按钮即可再次调用 API 并获取更多专辑。这也很好用...
问题
当我决定要拥有 2 个不同的 Facebook 页面并从中导入相册/照片时,我的问题出现了。所以我制作了一个带有 2 个选项的水平按钮(facebook 页面 1,facebook 页面 2),使导航栏保持不变,当我点击其中一个按钮时,我需要进行 API 调用并获取每个页面的相册。遗憾的是,这不起作用...当我调用两个页面之一时,一切正常。甚至“更多专辑”按钮也有效。但是当我导航到另一个 Facebook 页面时,对 api 的调用不起作用...我不明白为什么...“更多相册”按钮起作用,这意味着我可以多次调用 api。但是为什么当我使用 ajax 导航到 jquery 移动网站上的另一个页面时,调用无法完成?我在 javascript 文件中放置了一个警报,并且看到了它,这意味着该代码被调用。但是当我将警报放入对 api 的实际调用中时,我看不到任何警报......我想这意味着由于某种原因调用被阻止......
知道这里可能发生什么吗?
我的 2 张专辑之一的 javascript 如下所示:
$('#photosNJ').on("pageshow", function() {
var albumPhotos = new Array();
var albumThumbnails = new Array();
var x=0;
var next;
var times=0;
var dataLength=0;
// start the entire process
window.fbAsyncInit = function() {
// init the FB JS SDK
FB.init({
appId : '564984346887426', // App ID from the app dashboard
channelUrl : 'channel.html', // Channel file for x-domain comms
status : true, // Check Facebook Login status
xfbml : true // Look for social plugins on the page
});
$.mobile.loading("show");
FB.api('169070991963/albums', checkForErrorFirst(getAlbums));
//$.mobile.loading("hide");
}
// checkForErrorFirst wraps your function around the error checking code first
// if there is no response, then your code will not be called
// this allows you to just write the juicy working code
// and not worry about error checking
function checkForErrorFirst(myFunc) {
return function(response) {
if (!response || response.error) {
alert("Error !");
} else {
myFunc(response);
}
};
}
function getAlbums(response) {
//if statement checks , if there are any more albums to load. If not we disable the "More Albums" button.
if(response.paging.next == undefined) $("#loadMoreAlbums").parent().hide();
//variable next holds the URL for the next 25(or less) albums
next = response.paging.cursors.after;
dataLength = response.data.length + dataLength;
for (var i=0; i < response.data.length; ++i) {
processAlbum(response.data[i], i+x);
}
x = x+i;
console.log(x);
}
function processAlbum(album, i) {
FB.api(album.id + "/photos?limit=300", checkForErrorFirst(populateAlbum(album, i)));
}
function populateAlbum(album, i) {
return function(response) {
for (var k=0; k < response.data.length; ++k){
albumThumbnails[i] = albumThumbnails[i]||[];
albumThumbnails[i][k] = response.data[k].picture;
albumPhotos[i] = albumPhotos[i]||[];
albumPhotos[i][k] = response.data[k].source;
}
// now that we've populated the album thumbnails and photos, we can render the album
FB.api(album.cover_photo, checkForErrorFirst(renderAlbum(album, i)));
};
}
function renderAlbum(album, i) {
times++;
if(times == dataLength) $.mobile.loading("hide");
return function(response) {
var albumName = album.name;
var albumCover = album.cover_photo;
var albumId = album.id;
var numberOfPhotos = album.count;
// render photos
$(".albums").append('<li>'+
'<a href="#Gallery' + i + '"' + 'data-transition="slidedown">'+
'<img src= "' + response.picture + '" />'+
'<h2>' + albumName + '</h2>'+
'<p>' + "Number of Photos: " + numberOfPhotos +'</p>'+
'</a>'+
'</li>').listview('refresh');
$("#photosNJ").after('<div data-role="page" data-add-back-btn="true" id=Gallery'+ i +
' class="gallery-page"' + ' data-url="Gallery' + i + '"> ' +
' <div data-role="header"><h1>Gallery</h1></div> ' + ' <div data-role="content"> ' +
' <ul class="gallery"></ul> ' + ' </div> ' +
' </div> ');
for(var n=0; n < albumPhotos[i].length; n++) {
$('#Gallery' + i + ' .gallery').append('<li><a href="' + albumPhotos[i][n]
+ '" rel="external"><img src="' + albumThumbnails[i][n] + '"' + '/> </a> </li>');
}
//adding a "More Photos" button inside every album
// $('#Gallery' + i + ' .gallery').after('<button type="button" class="loadMorePhotos">More Photos...</button>');
};
}
// Load the SDK asynchronously
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
//"More Albums" button
$("#loadMoreAlbums").click(function(){
// start the entire process
window.fbAsyncInit = function() {
// init the FB JS SDK
FB.init({
appId : '564984346887426', // App ID from the app dashboard
channelUrl : 'channel.html', // Channel file for x-domain comms
status : true, // Check Facebook Login status
xfbml : true // Look for social plugins on the page
});
}
//when the "More Albums" button is pressed , we make a call at the API for the next 25(or less) albums , using the "next" URL
$.mobile.loading("show");
FB.api('169070991963/albums?after=' + next +"'", checkForErrorFirst(getAlbums));
});
});
您可以看到对 api 的调用、动态创建 html 页面以在 ListView 中显示相册、包含照片的相册数量、更多相册按钮等...我的其他 facebook 页面的 javascript是相同的,只有页面 ID 发生变化。此时,我想指出,如果我先加载另一个页面,然后再次加载这个页面,则第二个调用不起作用。这意味着我对其中一张专辑没有特定的问题,而不是第二个调用永远不会运行的问题。
这是 html 页面,以防您需要查看我到底想做什么:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jQuery Mobile Web App</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--<link href="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.css" rel="stylesheet" type="text/css"/>-->
<link rel="stylesheet" href="themes/EspacioJoven.min.css" />
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.1/jquery.mobile.structure-1.3.1.min.css" />
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.js"></script>
<link rel="stylesheet" href="themes/custom.css" />
<!--Used by PhotoSwipe Plugin -->
<script type="text/javascript" src="photoSwipe/klass.min.js"></script>
<script type="text/javascript" src="photoSwipe/code.photoswipe.jquery-3.0.5.min.js"></script>
<script type='text/javascript' src='photoSwipe/photoSwipeCall.js'></script>
<link href="photoSwipe/jquery-mobile.css" type="text/css" rel="stylesheet" />
<link href="photoSwipe/photoswipe.css" type="text/css" rel="stylesheet" />
<!--Used by PhotoSwipe Plugin -->
<script type='text/javascript' src='javascript/createFb2.js'></script>
<script type='text/javascript' src='javascript/createFb.js'></script>
</head>
<body>
<div data-role="page" id="home" data-theme = "a" >
<div data-role="content">
<h2 id="banner">Joven Mobile</h2>
<div class="main_menu">
<ul data-inset="true" data-role="listview">
<li><a href="#espaJoven"><img src="themes/icons/news.png" alt="Information" class="ui-li-icon">Es Joven</a></li>
<li><a href="#noJoven"><img src="themes/icons/research.png" alt="Information" class="ui-li-icon">La Noche es Joven</a></li>
<li><a href="#photosNJ"><img src="themes/icons/staff.png" alt="Information" class="ui-li-icon">Multimedia</a></li>
<li><a href="#sanrJoven"><img src="themes/icons/students.png" alt="Information" class="ui-li-icon">Sar Joven</a></li>
</ul>
</div> <!-- /main_menu -->
</div> <!-- /content -->
</div> <!-- /page -->
<div data-role="page" id="photosNJ" data-theme="a" data-add-back-btn="true" data-back-btn-text="Back">
<!--<script type='text/javascript' src='javascript/createFbAlbums.js'></script> -->
<div data-role="header" data-id="fixedNav" data-position="fixed">
<h1>Application Title</h1>
<a href="#" data-icon="back" data-rel="back" title="Go back">Back</a>
<div data-role="navbar">
<ul>
<li><a href="#photosNJ" class="ui-btn-active ui-state-persist">Photos Noche Joven</a></li>
<li><a href="#photosEJ">Photos Esp Joen</a></li>
<li><a href="#videos">Videos</a></li>
</ul>
</div> <!-- /navbar -->
</div> <!-- /header -->
<div data-role="content">
<ul data-role="listview" data-inset="true" class="albums">
<!-- Here the albums are created through javascript (createAlbums.js) -->
</ul>
<button type="button" id="loadMoreAlbums">More Albums...</button>
</div> <!-- /content -->
<!-- <div id="fb-root"></div> -->
</div>
<div data-role="page" id="photosEJ" data-theme="a" data-add-back-btn="true" data-back-btn-text="Back">
<!--<script type='text/javascript' src='javascript/createFbAlbums2.js'></script>-->
<div data-role="header" data-id="fixedNav" data-position="fixed">
<h1>Application Title</h1>
<a href="#" data-icon="back" data-rel="back" title="Go back">Back</a>
<div data-role="navbar">
<ul>
<li><a href="#photosNJ">Photos Noche Joven</a></li>
<li><a href="#photosEJ" class="ui-btn-active ui-state-persist">Photos Espacio Joven</a></li>
<li><a href="#videos">Videos</a></li>
</ul>
</div> <!-- /navbar -->
</div> <!-- /header -->
<div data-role="content">
<ul data-role="listview" data-inset="true" class="albums2">
<!-- Here the albums are created through javascript (createAlbums.js) -->
</ul>
<button type="button" id="loadMoreAlbums2">More Albums...</button>
</div> <!-- /content -->
<!-- <div id="fb-root"></div> -->
</div>
</body>
</html>
如果您决定读到这里,非常非常感谢。任何,绝对任何对此的评论或想法对我来说都非常有值(value),所以如果您有任何想法,请与我分享:)
fiddler : http://jsfiddle.net/lessisv/GW4PK/
转到多媒体,那里有 2 个选项卡“Photos Noche Joven”、“Photos Espacio Joven”。可以看到第一个加载正常。此外,如果您向下,您可以看到“更多相册”按钮,该按钮也可以正常工作并调用 API。问题是,当我转到“Photos Espacio Joven”时,由于我描述的原因,调用无法正常工作。
最佳答案
首先,您的 loadMoreAlbums
处理程序中不需要 window.fbAsyncInit
。您之前定义了相同的函数 - 这就足够了。
其次,您不会多次使用 FB.init
- 仅一次。因为它是在 window.fbAsyncInit
中定义的,并且该函数在加载 SDK 时由 Facebook SDK 调用。并且检查脚本是否已经加载:
if (d.getElementById(id)) {return;}
这意味着您加载 FB 脚本一次并初始化 FB 一次。
最主要的是,您不能在一个作用域(“pageshow event”处理程序之一)中初始化 FB 对象 (FB.init),然后在另一个作用域(另一个处理程序)中使用 FB.api。这就是为什么你得到空结果的原因。
您可以尝试多种解决方案。
1.每次页面变化时都可以初始化FB。
只需检查 FB 对象是否存在并调用 window.fbAsyncInit()。您可以通过更改来快速尝试此解决方案
if (d.getElementById(id)) {return;}
到
if (d.getElementById(id)) {window.fbAsyncInit(); return;}
这是一种丑陋的方式。
2.你真的应该重构你的代码。
在顶层初始化 FB - 不在两个处理程序中;创建一个处理程序 - 并在页面更改时调用它。您可以传递必要的参数或使用 DOM 元素数据。
PS。每次页面更改时都会添加一个新的 loadMoreAlbums 处理程序。您切换到另一个相册,返回并接到两个电话和双倍数据,再次切换并获得三倍数据。$(document).on("pageshow", '#photosNJ', function () {
...
$("#loadMoreAlbums").click(function () {
...
});
...
});
关于javascript - 多个异步调用(javascript facebook api)失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18270482/