JQuery loop and binding 10 records at a time

I have a scenario where I get thousands of records from the server as JSON and bind all the records to the page. For each entry, I do some calculations in jquery and data binding to the user interface. Since the number of records is 1000, the time to calculate and bind the data is longer. The data on the page is anchored at the end when all the records are calculated. Is it possible to bind data one by one or 10 by 10 and show the binding to the user interface for this set. What I'm trying to find is to execute $ .each for 10 records at a time and add the next set of 10 records to it and so on. any idea to speed up page loading? (Paging is not required for my requirement). Any clue can help.

<div id="keepFinalDataHere"></div>


$.each(data, function (i, record) {

 content += "<div>" + record.id + "</div><div>" + record.fromId + "</div><div>" + record.subject + "</div>";
        });

    $(content).appendTo('#keepFinalDataHere');

In the above code, the content is created by retrieving several thousand records and after creating the content, then it is attached to the div. I am looking for an option for the first 10 elements to bind data to make sure users feel that the page is loaded, and then ADD the remaining elements in sets of 100 or so to the existing list.

+4
source share
5 answers

If you want the user interface to respond and would like to be able to execute code between rendering a large number of DOM elements, you will have to use a timeout mechanism. You can do this by passing a rendering method setTimeout.

, setTimeout js-.

:

  • splice, n
  • n DOM
  • , (2)

, :

  • testData
  • createRow DOM
  • INITIAL_CHUNK_SIZE , -.
  • DEFAULT_CHUNK_SIZE ,

- (toRenderer):

var toRenderer = function(s) {
  // We need a copy because `splice` mutates an array
  var dataBuffer = [].concat(testData);

  var nextRender = function(s) {
    // Default value that can be overridden
    var chunkSize = s || DEFAULT_CHUNK_SIZE; 

    dataBuffer
      .splice(0, chunkSize)
      .forEach(createRow);

    if (dataBuffer.length) {
      setTimeout(nextRender);
    }
  };

  // Triggers the initial (not timed out) render
  nextRender(INITIAL_CHUNK_SIZE);
};

, , .

, DEFAULT_CHUNK_SIZE, . : 1/60, .

// SETTINGS
var DATA_LENGTH = 10000;
var DEFAULT_CHUNK_SIZE = 100;
var INITIAL_CHUNK_SIZE = 10;

var list = document.querySelector("ul");
var createRow = function(data) {
  var div = document.createElement("div");
  div.innerHTML = data;
  list.appendChild(div);
};

// Blocking until all rows are rendered
var bruteRenderer = function() {
  console.time("Brute renderer total time:");
  testData.forEach(createRow);
  console.timeEnd("Brute renderer total time:");
}

// Pushes "render assignments" to the "task que"
var toRenderer = function(s) {
  console.time("Timeout renderer total time:");
  var dataBuffer = [].concat(testData);

  var nextRender = function(s) {
    var chunkSize = s || DEFAULT_CHUNK_SIZE;

    dataBuffer
      .splice(0, chunkSize)
      .forEach(createRow);

    if (dataBuffer.length) {
      setTimeout(nextRender);
    } else {
      console.timeEnd("Timeout renderer total time:");
    }
  };

  nextRender(INITIAL_CHUNK_SIZE);
};

// EXAMPLE DATA, EVENT LISTENERS:


// Generate test data
var testData = (function() {
  var result = [];
  for (var i = 0; i < DATA_LENGTH; i += 1) {
    result.push("Item " + i);
  }
  return result;
}());

var clearList = function() {
  list.innerHTML = "";
};

// Attach buttons
document.querySelector(".js-brute").addEventListener("click", bruteRenderer);
document.querySelector(".js-to").addEventListener("click", toRenderer);
document.querySelector(".js-clear").addEventListener("click", clearList);
button {
  display: inline-block;
  margin-right: .5rem;
}
.spinner {
  background: red;
  border-radius: 50%;
  width: 20px;
  height: 20px;
  animation-duration: 1s;
  animation-timing-function: linear;
  animation-direction: alternate;
  animation-name: move;
  animation-iteration-count: infinite;
}
@keyframes move {
  from {
    transform: translate3d(800%, 0, 0);
  }
  to {
    transform: translate3d(0, 0, 0);
  }
}
ul {
  height: 200px;
  overflow-y: scroll;
  background: #efefef;
  border: 1px solid #ccc;
}
<button class="js-brute">
  Inject rows brute force
</button>
<button class="js-to">
  Inject rows timeout
</button>
<button class="js-clear">
  clear list
</button>

<pre></pre>
<div class="spinner"></div>

<ul>

</ul>
Hide result
+4

.

 <div id="keepFinalDataHere"></div>

<script>
//.../ 

var chunkSize = 50;//what ever you want or could be dynamic based on data size
var $keepFinalDataHere = $('#keepFinalDataHere');
$.each(data, function (i, record) {
  content += "<div>" + record.id + "</div><div>" + record.fromId + "</div><div>" + record.subject + "</div>";
     if(i % chunkSize === 0){ // content chunk is ready
          $keepFinalDataHere.append(content); // show records
          content = '';//reset the content
         }
    });
if(!(content === '')){//any leftOver records
   $keepFinalDataHere.append(content);
 }
+6

, , .

, , , .

, , .

( num?).

for.

// Globally but not global
var cursor = 0

... 


for(var i = cursor; i < (cursor+pageNum); i++) {
    var element = myDataAsJsonFromApi[i];
    // ... do something here.
}

// check if pageNum elements is added..
cursor += pageNum

if (myDataAsJsonFromApi.length == cursor) {
 // load from server...
}
+3
source

One option is to break the data buffer into pieces so that you can work with some data at the same time.

var data = [1,2,3,4,5,6,7,7,8,9,9,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,89];

(function () {

  var lastSliceStart = 0;

  function writeNext() {
    var length = 10;
    var chunk = $(data).slice(lastSliceStart, lastSliceStart+length);

    $(chunk).each((key, item) => {
      console.log(item);
    });

    lastSliceStart += length;

    if (lastSliceStart < data.length) {
      setTimeout(writeNext, 500); // Wait .5 seconds between runs
    }
  }

  writeNext();

})();

https://jsfiddle.net/bogfdmfb/1/

+3
source

Create a queue, a process queue for several items at a time, show the progress, process the next items in the queue, and so on.

//your app
App = {
    data: [] //set your JSON dataSource here
}

//define Task
Task = function () {        
    this.buildQueue(10);
};
Task.prototype = {
    buildQueue: function (size) {
        var data_count = App.data.length; //length of your datasource
        this.queue = [];                        
        // fill the queue
        var lastIndex = 0;
        var current_index = size;
        var c = true;
        while (c) {
            if (current_index >= data_count - 1) {
                current_index = data_count;
                c = false;
            }
            this.queue.push([lastIndex, current_index - 1]);
            lastIndex = current_index;
            current_index += size;
        }
        /* If size is 10, array would be [[0,9], [10,19], [20,29]....and so on], The smaller the size, better progress / percentage variation  / loading on ui display */
    },
    doNext: function () {
        if (this.queue.length == 0) {
            this.end();
            return;
        }            
        var row = this.queue.shift(); //stack is LIFO, queue is FIFO, this.queue.pop()
        try {
            this.processQueue(App.data, row[0], row[1]); //pass dataSource, and indexes of array, loop in processQueue function for indexes passed
        } catch (e) {                
            return;
        }
        this.incrementProgress(row[1] / App.data.length); //progress on ui
        // do next
        var _self = this;
        setTimeout(function () {
            _self.doNext();
        }, 1);
    },
    incrementProgress: function (percent) {
        var $progress = $('#percent');
        percent = Math.ceil(percent * 100);
        percent = percent + '%';
        $progress.text(percent);
    },
    start: function () {            
        $('#percent').show();
        this.doNext(); //initiate loop
    },
    end: function () {            
        $('#percent').hide();            
    },
    processQueue: function (data, start, end) {            
        for (var i = start; i <= end; i++) {                
            var dataObj = data[i];
            //use the data here, update UI so user sees something on screen
        }
    }
};

//initialize an instance of Task
var _task = new Task(task); 
_task.start();    
+3
source

All Articles