You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DataTables导出2万+记录报Maximum call stack size exceeded错误

问题根因

抛出Uncaught RangeError: Maximum call stack size exceeded错误的核心原因非常明确:你开启了DataTables的serverSide: true服务端处理模式,默认自带的excelHtml5/csvHtml5导出按钮是纯前端生成文件的逻辑:

  • 导出时会尝试拉取符合筛选条件的全量数据到浏览器内存,再通过递归遍历单元格拼接文件结构
  • 2000条以内数据时,递归调用深度在JS引擎默认栈阈值范围内,可以正常导出
  • 数据量达到2万条级别时,递归深度直接超出JS引擎栈上限,直接抛错。
    你之前搜到的所有同场景前端配置修改方案,都是针对客户端全量加载模式的,服务端模式下完全不生效——前端本身就没存储全量数据,硬要在浏览器端拼大体积文件本身就是错误的实现思路,就算临时绕过栈报错,也会因为占满内存导致页面卡顿、崩溃。
落地解决方案

彻底放弃前端生成导出文件的逻辑,改成服务端生成文件+前端触发下载的模式,从根源绕开前端性能瓶颈,不管导出多少条数据都不会触发前端报错。

1. 修改前端DataTables初始化配置

把原有前端导出按钮替换为自定义导出按钮,点击时携带当前筛选参数,直接请求后端导出接口,修改后的完整初始化代码如下:

table = $('#example').DataTable({ 
    dom: 'Bfrtip',
    buttons: [
        'copyHtml5',
        // 替换原excelHtml5为自定义Excel导出按钮
        {
            text: '导出Excel',
            action: function () {
                // 取当前筛选条件
                const reqParams = new URLSearchParams({
                    FromDate: $('#FromDate').val(),
                    ToDate: $('#ToDate').val(),
                    export_type: 'excel'
                });
                // 用隐藏表单提交,兼容各类浏览器的文件下载
                const submitForm = document.createElement('form');
                submitForm.method = 'POST';
                submitForm.action = 'http://100.250.90.110:8090/srx/voucher/export_credit_vouchers';
                submitForm.target = '_blank';
                reqParams.forEach((value, key) => {
                    const input = document.createElement('input');
                    input.name = key;
                    input.value = value;
                    submitForm.appendChild(input);
                });
                document.body.appendChild(submitForm);
                submitForm.submit();
                submitForm.remove();
            }
        },
        // 替换原csvHtml5为自定义CSV导出按钮
        {
            text: '导出CSV',
            action: function () {
                const reqParams = new URLSearchParams({
                    FromDate: $('#FromDate').val(),
                    ToDate: $('#ToDate').val(),
                    export_type: 'csv'
                });
                const submitForm = document.createElement('form');
                submitForm.method = 'POST';
                submitForm.action = 'http://100.250.90.110:8090/srx/voucher/export_credit_vouchers';
                submitForm.target = '_blank';
                reqParams.forEach((value, key) => {
                    const input = document.createElement('input');
                    input.name = key;
                    input.value = value;
                    submitForm.appendChild(input);
                });
                document.body.appendChild(submitForm);
                submitForm.submit();
                submitForm.remove();
            }
        },
        'pageLength'
    ],
    "pageLength": 25,
    "processing": true,
    "serverSide": true,
    "order": [],
    "aoColumnDefs": [{ "bSortable": false, "aTargets": [0]}],
    "bInfo": false,
    lengthMenu: [
        [ 10, 25, 50, -1 ],
        [ '10 rows', '25 rows', '50 rows', 'Show all' ]
    ],
    "ajax": {
        "url": "http://100.250.90.110:8090/srx/voucher/credit_vouchers_datatable",
        "type": "POST",
        "data": function ( data ) {
            data.FromDate   = $('#FromDate').val();
            data.ToDate     = $('#ToDate').val(); 
        }
    }
});

2. 新增CodeIgniter后端导出接口

在你的Voucher控制器下新增export_credit_vouchers方法,逻辑如下:

  • 接收前端传的FromDate、ToDate、export_type参数
  • 复用列表页的查询筛选条件,查询全量符合要求的数据,不要加分页参数
  • 导出前临时调整PHP配置,避免大数据量下超内存、超时:
    ini_set('memory_limit', '1024M');
    set_time_limit(300);
    
  • 根据export_type生成对应格式文件:
    • 导出CSV:输出带UTF-8 BOM头的CSV内容,设置响应头触发浏览器下载
    • 导出Excel:引入PhpSpreadsheet类库生成XLSX格式文件,直接输出到响应流触发下载

注意:查询全量数据时不要用框架的findAll一次性把所有结果加载到内存,可以用chunk分批读取数据写入文件,进一步降低服务端内存占用,支持几十万条以上的超大数据量导出。

方案优势
  • 彻底绕开前端JS处理大数据的栈溢出、内存溢出问题,浏览器只负责发起下载请求、接收文件,不会出现卡顿、崩溃问题
  • 导出数据量没有前端层面的限制,只要服务端性能足够,导出几十万条都可以正常运行
  • 导出逻辑和列表查询复用同一套筛选规则,不会出现导出内容和页面展示不一致的问题
避坑提示

不要尝试以下无效方案:

  • 修改DataTables源码调整递归逻辑、强行增大浏览器栈阈值:这类修改只对本地浏览器生效,普通用户访问依然会报错,且大文件生成时会占满用户设备内存
  • 配置导出按钮的serverSide参数让按钮分次拉取数据:拉取完成后依然要在前端拼接生成文件,数据量大了还是会爆栈、卡页

内容的提问来源于stack exchange,提问作者Niranjan Kumar Chowdam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 11:21:18