Jquery一次循环和绑定10条记录

时间:2016-07-06 21:56:47

标签: javascript jquery

我有一个场景,我从服务器获得数千条记录作为JSON并将所有记录绑定到页面。对于每条记录,我在jquery中进行一些计算并将数据绑定到UI。由于记录计数为1000,因此计算和绑定数据的时间更长。完成所有记录计算后,页面上的数据将被绑定。是否有任何选项可以逐个或10乘10绑定数据,并在UI上显示该集合的绑定。我想要找到的是一次为10条记录执行$ .each并将下一组10条记录附加到它上面,依此类推。任何想让页面加载更快的想法? (我的要求不需要分页)。任何线索都可以提供帮助。

<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');

在上面的代码中,内容是通过获取数千个记录来构建的,一旦构建了内容,它就被绑定到div。我正在寻找一个选项来获取前10个项目绑定数据,以确保用户感觉页面已加载,然后APPEND剩余项目100个左右的现有列表。

5 个答案:

答案 0 :(得分:6)

以简单的方式,你可以分块。

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

答案 1 :(得分:4)

如果您希望保持UI响应并希望能够在呈现大量DOM元素之间执行代码,那么您将不得不使用超时机制。您可以将渲染方法传递给setTimeout

不是将方法添加到堆栈并立即执行,T1 { S1 --->U1 } T2 { S2 ----->U2} 将方法推送到任务队列,只在当前js堆栈清除后才执行它。

我建议的方法的主要步骤:

  1. 将数据集复制到临时数组
  2. 使用setTimeout删除数组中的第一个splice
  3. 将第一个n项呈现给DOM
  4. 如果还有剩余项目,请转到(2)
  5. 这里是代码的主要部分,带有注释,假设:

    • n包含一系列数据点
    • testData拥有将数据点转换为渲染DOM元素的逻辑
    • createRow保存您想要呈现的行数而不会超时。
    • 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); }; 越大,您渲染所有项目的速度就越快。权衡:一旦渲染块超过1/60秒,你就会失去平滑的帧速率。

    &#13;
    &#13;
    DEFAULT_CHUNK_SIZE
    &#13;
    // 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);
    &#13;
    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;
    }
    &#13;
    &#13;
    &#13;

答案 2 :(得分:3)

如果您从服务器获取的数据量有问题,您应该找到一种方法来限制数组。

因此,您的客户端代码只能处理适当数量的元素,只能处理您可以向用户显示的元素。

如果这是不可能的,并且你想在客户端做所有事情,你应该有一个更复杂的方法。

您必须将指针保存到已处理的元素,以及一个包含要处理的元素数量的变量(页面数?)。

然后使用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 :(得分:3)

一种选择是将数据缓冲区拆分为块,这样您就可以一次对某些数据进行操作。

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/

答案 4 :(得分:3)

一次构建一个队列,处理几个项目的队列,显示进度,处理队列中的下一个项目等等。

//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();