我正在使用facebook的javascript sdk插件在我的网页上创建一个Feed。
问题在于,即使我已经设置了回调链,有时在加载期间Feed也会无序。
我认为它无序,因为有时候“第二次”异步调用的处理速度比“第一次”异步调用要快。
这是我第一次使用回调,我做得对吗?
如果某些通话比其他通话完成得快,我如何解决通讯无序?
以下代码仅为相关代码,处于工作状态。
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);
}
(对这篇文章的标题不确定,如果你认为它不够描述,请编辑) 最好的问候
答案 0 :(得分:2)
这是并行异步调用的一个常见问题。最简单的解决方案需要承诺。我推荐Bluebird promise库,但大多数都可以。
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可能就是其中之一。第一个在所有项目可用时呈现Feed,第二个在每个项目可用时呈现,但强制执行订单。
function initFeed(){
return Promise.all(getFeedItemPromises())
.then(function(itemsHtml){
// append all of the items at once
$('#fb-status-wrapper').append(itemsHtml.join("\n"));
});
}
或者这可以确保订单,但是在添加了所有之前的项目之后,急切地将项目附加到Feed。
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作为占位符,将它们保存在一个数组中,并在每个项目结算时填入它们。如果您事先知道物品的高度,并且在装载时淡入它们,则效果特别好。从用户体验的角度来看,这是我认为最好的。
如果您不知道项目的高度,我会不推荐以上内容,因为当插入新项目时,它会导致头痛导致项目移位。
答案 1 :(得分:1)
实际上,您不能依赖请求完成的顺序。唯一可以肯定的方法是,如果第一个完成,只调用第二个。但这会大大减慢负载。
另一种可能性是记住每个请求是哪一个,并以正确的顺序插入项目(在'之后'之前插入,即使之前收到的那个)。
我认为最简单的方法是为每个循环中的项目创建占位符,以便按正确的顺序插入占位符。当请求返回时,您只需将响应放在正确的占位符中。
看起来有点像这样。 2条额外的线条和几个微小的变化。没有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);
}