将返回 5000 行的 AJAX 调用拆分为包含 100 行的多个 AJAX 调用

Splitting an AJAX call which returns 5000 rows into multiple AJAX calls with 100 rows

本文关键字:AJAX 调用 包含 拆分 返回 5000 行的      更新时间:2023-09-26

我有一个 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 请求 - startbatchSize 。这些指示服务器端脚本返回哪批数据。

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

仅针对解析错误进行测试,因此可能需要调试

您仍然需要修改服务器端脚本以接受两个附加参数 startbatchsize并相应地编写其 SQL。这应该是相当微不足道的。

我最不确定的部分是makeRows(),我稍微挣扎了一下。如果没有任何效果,请先查看那里。