单击按钮时,我正在使用codeigniter从数据库中获取数据,并且div附加了所获取的数据。问题是,尽管数据量很大,但要花费时间,并且网页会滞后。我该怎么办才能解决此问题?
我的代码如下。
$("#get_spare_list").click(function() {
$("body").css("cursor", "progress");
var ht = "";
$.ajax({
url: "<?php echo base_url('Spare/get_all_spare_json'); ?>",
type: 'POST',
dataType: 'json',
data: {"param1": 'value1'},
})
.done(function(data) {
var no = 1;
var ht = "<table class='table'><thead><tr><th>No</th><th>Name</th><th>Code</th><th>Min qty</th><th>uni</th><th>Group</th><th>Sub Category</th><th>Part Number</th><th>Location</th><th>Image</th><th >Tyre</th><th>Back</th></tr></thead>";
$.each(data, function(key, val) {
ht +="<tr>"+"<td>"+no+"</td>"+"<td>"+val.name+"</td>"+"<td>"+val.code+"</td>"+"<td>"+val.min_qty+"</td>"+"<td>"+val.unit+"</td>"+"<td>"+val.group+"</td><td>"+val.sub_category+"</td><td>"+val.part_number+"</td><td>"+val.location+"</td>";
if (val.image) {
ht += "<td><a target='_blank' href='"+"<?php echo base_url('../uploads/'); ?>/"+val.image+"'><button class='fa fa-picture-o'></button></a></td>";
}else{
ht += "<td></td>";
}
ht +="<td>"+val.tyre+"</td>";
ht += "<td>";
if (val.reusable == 1) {
ht +="yes";
}else{
ht+="no";
};
ht += "</td>";
ht += "<td><button class='btn edit btn-info btn-xs' data-toggle='modal' data-target='#editModel' data-id='"+val.id+"' data-name='"+val.name+"' data-code='"+val.code+"' data-min_qty='"+val.min_qty+"' data-unit='"+val.unit+"' data-group='"+val.group+"' data-sub_category='"+val.sub_category+"' data-part_number='"+val.part_number+"' data-location='"+val.location+"' data-tyre_number='"+val.tyre+"' data-back='"+val.reusable+"'><span class='fa fa-edit'></span></button></td>";
ht += "</tr>";
no++;
});
$("#js_res").append(ht);
$("body").css("cursor", "default");
})
.fail(function() {
alert("error");
$("body").css("cursor", "default");
});
});
jQuery应该平稳地将数据追加到div,而不会滞后于网页。
答案 0 :(得分:1)
当浏览器收到响应时,传递给.done()
的回调函数将添加到JavaScript的事件循环队列中。
在处理数据时,它会阻塞JavaScript的事件循环以处理其他任务。同时,甚至诸如处理鼠标输入之类的东西也被阻止了。如果要处理的数据太大,则最终用户将更容易观察到。
您可以将调用的数据setTimeout()
划分为多个块并将其分别推送到事件循环。来源:Cooperation part of You Don't Know JS: Async & Performance
以下是如何处理您的代码,传递给.done()
的回调函数和辅助函数的方法:
function(data) {
var ht = "<table class='table'><thead><tr><th>No</th><th>Name</th><th>Code</th><th>Min qty</th><th>uni</th><th>Group</th><th>Sub Category</th><th>Part Number</th><th>Location</th><th>Image</th><th >Tyre</th><th>Back</th></tr></thead>";
$("#js_res").append(ht);
processData(data, 1);
$("body").css("cursor", "default");
}
function processData(data, no) {
var chunk = data.splice(0, 100);
var ht = "";
$.each(chunk, function(key, val) {
ht +="<tr>"+"<td>"+no+"</td>"+"<td>"+val.name+"</td>"+"<td>"+val.code+"</td>"+"<td>"+val.min_qty+"</td>"+"<td>"+val.unit+"</td>"+"<td>"+val.group+"</td><td>"+val.sub_category+"</td><td>"+val.part_number+"</td><td>"+val.location+"</td>";
if (val.image) {
ht += "<td><a target='_blank' href='"+"<?php echo base_url('../uploads/'); ?>/"+val.image+"'><button class='fa fa-picture-o'></button></a></td>";
}else{
ht += "<td></td>";
}
ht +="<td>"+val.tyre+"</td>";
ht += "<td>";
if (val.reusable == 1) {
ht +="yes";
}else{
ht+="no";
};
ht += "</td>";
ht += "<td><button class='btn edit btn-info btn-xs' data-toggle='modal' data-target='#editModel' data-id='"+val.id+"' data-name='"+val.name+"' data-code='"+val.code+"' data-min_qty='"+val.min_qty+"' data-unit='"+val.unit+"' data-group='"+val.group+"' data-sub_category='"+val.sub_category+"' data-part_number='"+val.part_number+"' data-location='"+val.location+"' data-tyre_number='"+val.tyre+"' data-back='"+val.reusable+"'><span class='fa fa-edit'></span></button></td>";
ht += "</tr>";
no++;
});
$("#js_res").append(ht);
if (data.length > 0) {
setTimeout(function(){
processData(data, no);
}, 0);
}
}
答案 1 :(得分:0)
另一种解决方案是使用web worker处理这些表行的创建。
网络工作者无法编辑DOM,但您可以将数据传递给网络工作者。然后,工作人员可以创建html字符串,并将其传递回主JS线程,然后可以附加它。
var myWorker = new Worker('create-table.js');
// after successful ajax call, hand data over to worker
myWorker.postMessage(data);
console.log('Message posted to worker');
在create-table.js
内,我们可以指定我们的工作人员:
onmessage = function(e) {
console.log('Message received from main script');
/*
This is just an example from mdn documentation
Obviously you should recreate your logic for creating your <tr> here
*/
var workerResult = 'Result: ' + (e.data[0]);
console.log('Posting message back to main script');
postMessage(workerResult);
}
然后在主js文件中,您可以对工作程序的结果做出如下反应:
myWorker.onmessage = function(e) {
$("#js_res").append(e.data)
console.log('Message received from worker');
}