Javascript回调的处理速度比其他人快

时间:2014-10-25 10:04:57

标签: javascript jquery facebook-javascript-sdk

我正在使用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);
}

(对这篇文章的标题不确定,如果你认为它不够描述,请编辑) 最好的问候

2 个答案:

答案 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);
}