我正在使用facebook的javascript sdk插件在我的网页上创建提要。
问题是,有时在加载过程中,即使我设置了回调链,提要也会变得无序。
我认为它是无序的,因为有时"第二个"异步调用的处理速度比"第一个"异步呼叫快。
这是我第一次使用回调,我做得对吗?
如果某些调用完成得比其他调用快,我如何解决提要无序的问题?
以下代码仅为相关代码,处于工作状态。
function initFeed(){
FB.api('/{id}/feed', function(response){
var feedArray = response.data;
$.each(feedArray, function(){
var $this = $(this)[0]; //Status Object for single Status in Feed
setStatus($this, processStatus); //processStatus is function defined below
});
});
}
function setStatus(statusObject, callbackProcessStatus){
FB.api("/{personId}?fields=id,link,name,picture",
function (response) {
var html = /* Generates html based from statusObject and response */
callbackProcessStatus(html);
});
}
function processStatus(html){
$('#fb-status-wrapper').append(html);
}
(不确定这篇文章的标题,如果你认为它不够描述性,请编辑)向致以最良好的问候
这是并行异步调用的一个常见问题。最简单的解决方案需要承诺。我推荐蓝鸟承诺图书馆,但大多数都会做得很好。
var fbApi = function(url){
return new Promise(function(resolve, reject){
FB.api(url, function(resp){ resolve(resp); });
});
}
function setStatus(statusObject){
return fbApi("/{personId}?fields=id,link,name,picture")
.then(function(response){
var html = ...;
return html;
});
}
function getFeedItemPromises(){
return fbApi("/{id}/feed").then(function(response){
return response.data.map(function(item){
});
});
}
根据您的需要,initFeed可以是其中之一。第一个在所有项目都可用时渲染提要,第二个在每个项目都可用但强制执行顺序时渲染提要。
function initFeed(){
return Promise.all(getFeedItemPromises())
.then(function(itemsHtml){
// append all of the items at once
$('#fb-status-wrapper').append(itemsHtml.join("n"));
});
}
或者这确保了顺序,但在添加了之前的所有项目后,会急切地将项目附加到提要中。
function initFeed(){
function renderItem(html){
$('#fb-status-wrapper').append(html);
}
// reduce can be used to chain promises in sequence
return getFeedItemPromises().reduce(function(p, nextPromise){
return p.then(function(){ return nextPromise })
.then(renderItem);
}, Promise.resolve())
}
另一种选择是为每个项创建一个div,作为占位符,将它们保存在数组中,并在每个项解析时填充它们。如果您事先知道项目的高度,并在加载时将其淡入,则效果尤其好。从用户体验的角度来看,这是我认为最好的。
如果你不知道物品的高度,我不推荐使用上述方法,因为插入新物品时会导致令人头痛的物品移位。
实际上,您不能依赖于请求的完成顺序。唯一可以确定的方法是,如果第一个完成,只调用第二个。但这会大大降低装载速度。
另一种可能性是记住每个请求是哪一个,并按正确的顺序插入项目(在"较晚"的请求之前插入,即使该请求是较早收到的)。
我认为最简单的方法是为每个循环中的项制作占位符,以便按正确的顺序插入占位符。当请求返回时,您只需将响应放在正确的占位符中。
它可能看起来有点像这样。两条额外的线和一些微小的变化。如果没有API,我无法测试这一点,但我希望你能明白。
function initFeed(){
FB.api('/{id}/feed', function(response){
var feedArray = response.data;
$.each(feedArray, function(index){
var $this = $(this)[0]; //Status Object for single Status in Feed
// Make a container per item inside the wrapper.
var $itemContainer = $('<div></div>');
$('#fb-status-wrapper').append($itemContainer);
// Pass the container to the api function.
setStatus($this, processStatus, $itemContainer); //processStatus is function defined below
});
});
}
function setStatus(statusObject, callbackProcessStatus, $container){
FB.api("/{personId}?fields=id,link,name,picture",
function (response) {
var html = /* Generates html based from statusObject and response */
// Pass the item place holder/container to the processing procedure.
callbackProcessStatus(html, $container);
});
}
function processStatus(html, $container){
$container.append(html);
}