将返回 5000 行的 AJAX 调用拆分为包含 100 行的多个 AJAX 调用
Splitting an AJAX call which returns 5000 rows into multiple AJAX calls with 100 rows
我有一个 ajax 调用,我正在将返回的数据加载到数据表中
这是我的 jquery ajax 调用
<script type="text/javascript">
var oTable;
$(document).ready(function() {
window.prettyPrint() && prettyPrint();
$('#load').click(function()
{
var v = $('#drp_v').val();
var cnt = $('#drp_cnt').val();
var ctg = $('#drp_ctg').val();
var api = $('#drp_api').val();
var nt = $('#drp_nt').val();
$.post("ajax.php",
{ 'version':v,'category':ctg,
'country':cnt,'network_id':nt,
'api':api,'func':'show_datatable'},
function(data)
{
var aColumns = [];
var columns = [];
for(var i = 0; i < data.length; i++)
{
if(i>0)
break;
keycolumns = Object.keys(data[i]);
for(j = 0; j < keycolumns.length; j++)
{
if($.inArray(keycolumns[j],aColumns.sTitle)<=0)
{
aColumns.push({sTitle: keycolumns[j]}) //Checks if
columns.push(keycolumns[j]) //Checks if
}
}
}
var oTable = $('#jsontable').dataTable({
"columns":aColumns,
"sDom": 'T<"clear">lfrtip',
"oTableTools": {
"aButtons": [
{
"sExtends": "csv",
"sButtonText": "CSV",
}
]
}
});
oTable.fnClearTable();
var row = []
for(var i = 0; i < data.length; i++)
{
for(var c = 0; c < columns.length; c++)
{
row.push( data[i][columns[c]] ) ;
}
oTable.fnAddData(row);
row = [];
}
},'json');
});
});
</script>
这是我的php函数
function show_datatable($version,$ctg,$cnt,$nt,$api)
{
$cnt_table = "aw_countries_".$version;
$ctg_table = "aw_categories_".$version;
$off_table = "aw_offers_".$version;
$sizeof_ctg = count($ctg);
$cond_ctg = " ( ";
for($c = 0; $c < $sizeof_ctg ; $c++)
{
$cond_ctg = $cond_ctg." $ctg_table.category = '".$ctg[$c]."' ";
if($c < intval($sizeof_ctg-1))
$cond_ctg = $cond_ctg." OR ";
else if($c == intval($sizeof_ctg-1))
$cond_ctg = $cond_ctg." ) ";
}
$sizeof_cnt = count($cnt);
$cond_cnt = " ( ";
for($cn = 0; $cn < $sizeof_cnt ; $cn++)
{
$cond_cnt = $cond_cnt." $cnt_table.country = '".$cnt[$cn]."' ";
if($cn < intval($sizeof_cnt-1))
$cond_cnt = $cond_cnt." OR ";
else if($cn == intval($sizeof_cnt-1))
$cond_cnt = $cond_cnt." ) ";
}
$sizeof_nt = count($nt);
$cond_nt = " ( ";
for($n = 0; $n < $sizeof_nt ; $n++)
{
$cond_nt = $cond_nt." $off_table.network_id = '".$nt[$n]."' ";
if($n < intval($sizeof_nt-1))
$cond_nt = $cond_nt." OR ";
else if($n == intval($sizeof_nt-1))
$cond_nt = $cond_nt." ) ";
}
$sizeof_api = count($api);
$cond_api = " ( ";
for($a = 0; $a < $sizeof_api ; $a++)
{
$cond_api = $cond_api." $off_table.api_key = '".$api[$a]."' ";
if($a < intval($sizeof_api-1))
$cond_api = $cond_api." OR ";
else if($a == intval($sizeof_api-1))
$cond_api = $cond_api." ) ";
}
$output = "";
$sql = "SELECT *
FROM $off_table,$cnt_table,$ctg_table
WHERE $off_table.id = $cnt_table.id
AND $off_table.id = $ctg_table.id
AND ".$cond_api."
AND ".$cond_nt."
AND ".$cond_cnt."
AND ".$cond_ctg;
$result = mysql_query($sql);
$arr_result = array();
while($row = mysql_fetch_assoc($result))
{
$arr_result[] = $row;
}
$arr_result_enc = json_encode($arr_result);
echo $arr_result_enc;
}
现在,我想修改此代码。假设我想像这样工作:
我将调用 v,AJAX 将一次向我发送 100 行,然后再次发送 100 行,然后再次发送 100 行。
我的意思是拆分 AJAX 调用以一个接一个地返回所有数据的块。假设会多次调用 AJAX,每次它都会向我发送 100 个数据块。
在工作进行的同时,将有一个带有取消按钮的进度条。
如果我单击取消按钮,那么如果调用了 3 次 AJAX 函数,它将向我显示 300 个数据,然后 AJAX 将被停止。数据库将仅显示 300 个数据。
JQ:
// counter that allows you to get a new set of rows
var step = 0;
// set variable if you want to restrict the number of rows will be loaded
var maxStep = 0;//
// how many rows should be returned
var count = 100;
// if the cancel button is pressed
var cancel = false;
$(function() {
$('#load').click(function(){
getData();
})
$('#cancel').click(function(){
cancel = true;
})
});
function getData()
{
step++;
//If cancel variable is set to true stop new calls
if(cancel == true) return;
// checks if the variable is set and limits how many rows to be fetched
if(maxStep >0 and step >= maxStep) return;
$.post('ajax.php'
,{
'step':step,
'count':count,
}
,function(data, textStatus, jqXHR){
// do something with the data
// when it finishes processing the data, call back function
getData();
}
,'json'
)
}
阿贾克斯。.PHP
$step = 0;
if(isset($_POST['step'])) $step = (int)$_POST['step'];
$count = 0;
if(isset($_POST['count'])) $count = (int)$_POST['count'];
if($step>0 and $count>0)
{
$offset = ($step-1) * $count;
$limit = $offset.','.$count;
// --------------
// your code here
// --------------
$sql = "SELECT *
FROM $off_table,$cnt_table,$ctg_table
WHERE $off_table.id = $cnt_table.id
AND $off_table.id = $ctg_table.id
AND ".$cond_api."
AND ".$cond_nt."
AND ".$cond_cnt."
AND ".$cond_ctg."
LIMIT ".$limit;// <- limit
$result = mysql_query($sql);
$arr_result = array();
while($row = mysql_fetch_assoc($result))
{
$arr_result[] = $row;
}
$arr_result_enc = json_encode($arr_result);
echo $arr_result_enc;
// echo rows
echo json_encode($rows);
}
客户端代码的大量重构,其中整个过程被分成三个独立的函数getBatch()
、makeRows()
和showData()
,并由原始点击处理程序的一个非常修改的版本开始。
批处理由 getBatch()
控制,它使用两个额外的参数发出 ajax 请求 - start
和 batchSize
。这些指示服务器端脚本返回哪批数据。
makeRows()
和showData()
只是getBatch()
调用的同步工作器函数。
我假设进度是在 DOM 元素"#progress"中报告的。您可以在此处报告您喜欢的内容。我保持简单,显示累积的行数。通过添加批处理计数器,还可以显示已完成的批处理数。
通过将外部变量allowBatch
设置为 false
来实现取消。将继续找到当前请求的批次,但将撤回检索更多批次的权限。
为了更好地衡量,在过程的开始和结束时启用/禁用或显示/隐藏各种 DOM 元素。如果不需要,可以省略。
var oTable;
$(document).ready(function() {
window.prettyPrint() && prettyPrint();
var aColumns = [],
columns = [],
rows = [],
$progress = $("#progress"),
allowBatch;
function getBatch(options) {
return $.post("ajax.php", options, 'json').then(function(data) {
var promise;
if(allowBatch && data && data.length) {
$progress.text(makeRows(data));
options.start += batchsize;
promise = getBatch(options);
} else {
promise = $.when(showData());
}
return promise;
});
}
function makeRows(data) {
var keycolumns, i, j;
if(aColumns.length == 0) {
keycolumns = Object.keys(data[0]);
for(j = 0; j < keycolumns.length; j++) {
if($.inArray(keycolumns[j], aColumns.sTitle) <= 0) {
aColumns.push({sTitle: keycolumns[j]});
columns.push(keycolumns[j]);
}
}
}
for(i = 0; i < data.length; i++) {
rows.push( columns.map(function(col) {
return data[i][col];
}) );
}
return rows.length;
}
function showData() {
var oTable = $('#jsontable').dataTable({
'columns': aColumns,
'sDom': 'T<"clear">lfrtip',
'oTableTools': {
"aButtons": [{
"sExtends": "csv",
"sButtonText": "CSV"
}]
}
});
oTable.fnClearTable();
$.each(rows, function(row) {
oTable.fnAddData(row);
});
return oTable;
}
$('#load').on('click', function(e) {
e.preventDefault();
var $load = $(this).attr('disabled', true),
$cancel = $("#cancel").show();
$progress.text('').show();
aColumns.length = columns.length = rows.length = 0;
allowBatch = true;
getBatch({
'version': $('#drp_v').val(),
'category': $('#drp_ctg').val(),
'country': $('#drp_cnt').val(),
'network_id': $('#drp_nt').val(),
'api': $('#drp_api').val(),
'func': 'show_datatable',
'start': 0,
'batchsize': 100
}).then(function(oTable) {
// ... all done
$load.attr('disabled', false);
$cancel.hide();
$progress.hide();
});
});
$("#cancel").on('click', function(e) {
e.preventDefault();
allowBatch = false;
}).hide();
$("#progress").hide();
});
仅针对解析错误进行测试,因此可能需要调试
您仍然需要修改服务器端脚本以接受两个附加参数 start
和 batchsize
并相应地编写其 SQL。这应该是相当微不足道的。
我最不确定的部分是makeRows()
,我稍微挣扎了一下。如果没有任何效果,请先查看那里。
- 另一个ajax调用中的Jquery ajax调用在for循环中没有按预期工作
- Javascript/jQuery中的并行Ajax调用
- 任何方式使AJAX调用Gmail API,而无需通过JS库
- node.js请求数据事件未在CORS ajax调用中触发
- 如何从ajax调用返回.wrap()元素
- Ajax调用在Firefox中不会自动响应
- AJAX调用中的非法调用
- 使用AJAX调用将GeoJSON数据拉入传单
- 在MVC 4中,对Controller的Ajax调用为空
- Jquery:对返回JSON数据的php脚本的Ajax调用
- 在ajax调用中阻止来自JS对象的函数
- 如何在MVC5中ajax调用的部分视图中引用外部javascript
- 页面加载后的Ajax调用
- 如何使用Ajax调用特定的控制器和操作来重定向用户
- curl和fileget_contents在ajax调用后不起作用
- 在任何AJAX调用之前触发一个javascript函数
- 无法在mvc视图中使用ajax调用获取操作返回的模型对象列表
- Ajax调用ERror Cross Origin REquest:在rails中自动完成大学列表
- ASP.NET MVC 3-在ajax调用后,重定向到新页面或生成页面刷新
- 点击功能没有'ajax调用动态元素(Backbone)后无法工作