KnockoutJS - foreach绑定中的异步加载

时间:2016-08-12 01:56:43

标签: javascript knockout.js

我在使用KnockoutJS foreach绑定和大型数据集时遇到了问题。目前,我将容器div的“数据”绑定设置为一个函数,该函数执行ajax调用以获取数据,在JS对象中解析它,并将每个结果推送到一个可观察的数组中。

当我的数据集很小(0-50)时,这种方法很有效。但是,一旦我开始有100多条记录,总时间就会急剧增加。我发现只要数据开始处理,浏览器的线程就会被“锁定”,直到所有元素都被解析并添加到数组中。最后,它会将内容加载到dom上并立即“弹出”。

我想知道是否有办法通过延迟将元素加载到DOM中来修改它。具体来说,我希望DOM在处理每个元素时呈现它们,而不是等待所有元素被处理。

由于

1 个答案:

答案 0 :(得分:0)

由于您尚未发布代码段,因此我解释了您可以执行的一种可能方法。 您可以更改服务器端代码,以便以能够处理延迟加载的方式返回数据。
然后你需要有一个间隔函数来持续调用一个函数,如果你的最后一个ajax调用返回数据,你在该函数内检查一个标志,然后它调用下一个ajax。
在您的响应中,数据具有跟踪是否有更多数据,总项目等的属性。然后在您的Ajax成功中回调更新observables变量,您可以使用它们发送您的请求数据,如NextPage等,如果没有更多数据,你取消了setInterval函数。

以下是您如何实施此方法的示例(未经测试)
JS:

var YourViewModel = function () {
    var self = this ;
    var loadMoreTimer;
    self.IsMoreItems = ko.observable(false);
    self.LoadingMoreInProcess = ko.observable(false);
    self.CurrentPage = ko.observable(0);
    self.Items = ko.observableArray([]);

    self.AutomaticLoadItem = function () {
      loadMoreTimer = setInterval(callLoadMore, 500);
    }

    function callLoadMore() {
      if (self.IsMoreItems()) {
        if (!self.LoadingMoreInProcess()) {
          self.LoadMore();
        }
      } 
    }
    self.LoadMore = function () {
      self.CurrentPage(self.CurrentPage() + 1);
      self.LoadingMoreInProcess(true);
      data = {requestPage : self.CurrentPage(), numberOfItem : 20, ...}
      //your ajax call here
        $.ajax({
            url:..., 
            type: ....,      
            data: data,     
            success: function(response){ 
             // here you check if there is more data left 
              if(response.isMoreData){
               // set it to false so the next ajax call can be executed.
                self.LoadingMoreInProcess(false);
               // map through your data and push each item into the observableArray 
                 $.map(response.Items, function (item) {
                     self.Items.push(new ItemDetailViewModel(item));
                  });
              }else{
               // if there is no more data stop the interval function.
                clearInterval(loadMoreTimer);
              }
            }                         

        })
    }
  //Call to start lazy loading
  self.AutomaticLoadItem();
 }

var ItemDetailViewModel = function (data){
  var self = this ;
  self.Id = data.Id ;
  self.Name = data.Name;
  // .....
}