简体   繁体   中英

KnockoutJS - Asynchronous loading in foreach binding

I'm having an issue using KnockoutJS foreach binding in conjunction with a large dataset. Currently, I have my container div's "data" binding set to a function that performs an ajax call to get the data, parses it in JS objects, and pushes each result into an observable array.

This approach works great when my dataset is small (0-50). However, as soon as I start having 100+ records, the total time increases dramatically. I am finding that as soon as the data starts being processed, the browser's thread will get "locked" until all elements are parsed and added to the array. Finally, it will load the content onto the dom and all "pop in" at once.

I am wondering if there is a way to modify this by lazy loading the elements into the DOM. Specifically, I would like the DOM to render each element as it is being processed instead of waiting for all of them to be processed.

Thanks

Since you have've not posted a code snippet I explain one of the possible approaches that you can do. You can change your server-side code where you are returning back your data in a way that would be able to handle a lazy loading.
Then you need to have an interval function that keeps calling a function which inside that function you check a flag if your last ajax call return back data, then it calls the next ajax.
In your response data have properties to track if there is more data, total items, etc.Then in your Ajax success call back update observables variables that you may use them to send your request data like NextPage, etc. if there is no more data, you cancel the setInterval function.


Below is just an example of how you can implement this approach (Not tested)
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;
  // .....
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM