如何使两个异步API调用一个接一个地执行
How to make 2 asynchronous API calls execute one after another
我正在使用facebooks javascript API
从Facebook页面导入albums
和photos
。
首先,我使用API调用导入albums
。
然后我用另一个API调用将每个album
的photos
导入到数组中。
最后一步-通过另一个API调用,我导入每个相册的coverPhotos
,这样我就可以用所有的albums
和它们的coverPhotos
制作jquery mobile listView
。
我的代码如下:
<script>
var albumPhotos = new Array();
var albumThumbnails = new Array();
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
});
// Additional initialization code such as adding Event Listeners goes here
FB.api('169070991963/albums', function(response) {
if(!response || response.error) {
// render error
alert("Noo!!");
} else {
// render photos
for(var i=0; i<response.data.length; i++) {
(function (i) {
var albumName = response.data[i].name;
var albumCover = response.data[i].cover_photo;
var albumId = response.data[i].id;
var numberOfPhotos = response.data[i].count;
FB.api(albumId + "/photos", function(response) {
if(!response || response.error) {
// render error
alert("Noo!!");
} else {
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;
}
}
});
console.log(albumName);
FB.api( albumCover, function(response) {
if(!response || response.error) {
// render error
alert("Noo!!");
} else {
// 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');
$("#home").after('<div data-role="page" data-add-back-btn="true" id=Gallery'+ i +
' class="gallery-page"> ' +
' <div data-role="header"><h1>Gallery</h1></div> ' + ' <div data-role="content"> ' +
' <ul class="gallery"></ul> ' + ' </div> ' +
' </div> ');
for(var x=0; x < albumPhotos[i].length; x++)
$('#Gallery' + i + ' .gallery').append('<li><a href="' + albumPhotos[i][x] + '" rel="external"><img src="' + albumThumbnails[i][x] + '" /></a></li>');
}
});
})(i);
} //end of for loop
}
});
};
我在这段代码中遇到了一个问题:
for(var x=0; x < albumPhotos[i].length; x++)
$('#Gallery' + i + ' .gallery').append('<li><a href="' + albumPhotos[i][x] + '" rel="external"><img src="' + albumThumbnails[i][x] + '" /></a></li>');
更具体地说:albumPhotos[i].length
由于对API的调用是异步的,因此实际创建数组albumPhotos
的上一个API调用尚未完成,这意味着数组尚未定义。
在调用最后一个API调用FB.api(albumCover, function(response) {..}
之前,我需要一种方法
以确保上一个API调用:
FB.api(albumId + "/photos", function(response) {
if(!response || response.error) {
// render error
alert("Noo!!");
} else {
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;
}
}
});
已完成。
在这里,最简单的方法是什么?
简言之,您需要使所有依赖于要填充的相册的代码在填充后都能工作。这意味着复制并粘贴一些代码。
答案很长。。。
首先,让我们进行一些重构。为了你的理智,你会想要这个功能
// 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("Noo!!");
} else {
myFunc(response);
}
};
}
这样你就可以做这样的事情:
function DoWork(response) {
// usefulwork...
}
FB电话看起来。。。
FB.api('169070991963/albums', checkForErrorFirst(DoWork));
既然我们已经解决了这个问题,我们需要把你的每一个电话都联系在一起,因为它们相互依赖。我像你一样在全球空间中设置了相册照片和相册缩略图。
var albumPhotos = new Array();
var albumThumbnails = new Array();
function getAlbums(response) {
for (var i=0; i < response.data.length; ++i) {
processAlbum(response.data[i], i);
}
}
function processAlbum(album, i) {
FB.api(album.id + "/photos", 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) {
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');
$("#home").after('<div data-role="page" data-add-back-btn="true" id=Gallery'+ i +
' class="gallery-page"> ' +
' <div data-role="header"><h1>Gallery</h1></div> ' + ' <div data-role="content"> ' +
' <ul class="gallery"></ul> ' + ' </div> ' +
' </div> ');
for(var x=0; x < albumPhotos[i].length; x++)
$('#Gallery' + i + ' .gallery').append('<li><a href="' + albumPhotos[i][x]
+ '" rel="external"><img src="' + albumThumbnails[i][x] + '" /></a></li>');
};
}
// start the entire process
FB.api('169070991963/albums', checkForErrorFirst(getAlbums));
很明显,我还没有测试过这一点,但我认为这会对你的理智有所帮助。
相关文章:
- jQuery-将列表项的一个元素移动到同一项的另一个元素中+对我的列表中的每个项执行此操作
- jQuery-在页面加载时执行一个函数
- 如何从另一个处理程序内部取消JavaScript事件处理程序函数的执行
- 如何打开一个新窗口或选项卡,并将其提供给javascript执行
- 在Javascript中一个接一个地执行一个函数
- 有没有一种方法可以检查javascript以毫秒为单位执行一个函数需要多长时间
- 你能用sound.js在播放声音文件后5秒执行一个动作吗
- 在页面内执行一个javascript函数作为last
- javascript下载一个文件并执行提交操作
- Rails 4、Turbolink在渲染一个部分后执行javascript
- 停止从另一个函数执行Javascript函数
- 如何生成一个执行AJAX调用的函数
- 执行一系列 Javascript 承诺一个接一个地解决
- 角度 2:使用一个 http 调用的结果来执行另一个调用
- 与 promise 一起使用时,异步瀑布不执行下一个回调方法
- 从一个文本框执行代码,并在另一个文本框中以 HTML 显示输出
- 是节点.js一次只执行一个上下文
- 仅在堆栈中的最后一个执行回调
- JavaScript:一个接一个执行多个REST调用的正确方法
- post请求总是在angularjs函数的最后一个执行(不是按顺序执行)