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

解决DataTable重复初始化引发的Maximum call stack size exceeded错误

解决DataTable重复初始化引发的栈溢出错误

错误现象

控制台抛出栈溢出错误:

code.jquery.com_jquery-3.7.0.js:3871 Uncaught RangeError: Maximum call stack size exceeded
    at access (code.jquery.com_jquery-3.7.0.js:3871:22)
    at jQuery.fn.init.attr (code.jquery.com_jquery-3.7.0.js:7862:10)
    at containsPmdClassPrefix (pro.propeller.in_docs_js_propeller-user-manual.js:181:15)
    at processNode (pro.propeller.in_docs_js_propeller-user-manual.js:149:8)
    at pro.propeller.in_docs_js_propeller-user-manual.js:173:6
    at pro.propeller.in_docs_js_propeller-user-manual.js:139:5
    at pro.propeller.in_docs_js_propeller-user-manual.js:174:7
    at pro.propeller.in_docs_js_propeller-user-manual.js:174:7

问题定位

报错源于多处重复销毁/初始化DataTable实例,以及冗余的循环检测逻辑:

  1. 下拉框change事件中手动销毁表格后,又调用create_certain_ipc_log_table,而该函数内部再次执行销毁+初始化操作,导致重复触发。
  2. checkSelectChange函数通过requestAnimationFrame无限循环,且内部直接操作表格时dataToUse未定义,触发无效的表格初始化逻辑,加剧循环调用。
  3. 原表格初始化代码未彻底清理实例状态,导致DOM与DataTable实例绑定混乱。

优化解决方案

核心修改点

  • 移除冗余的checkSelectChange循环检测逻辑,下拉框change事件已足够处理表格更新。
  • 统一表格初始化逻辑,在create_certain_ipc_log_table中确保实例彻底销毁后再重建,避免重复操作。
  • 简化下拉框change事件代码,不再手动销毁表格,交由create函数统一处理。

修正后的关键代码段

// 移除原有的checkSelectChange函数及调用
// function checkSelectChange() { ... }
// requestAnimationFrame(checkSelectChange);

// 修正下拉框change事件
$("#exampleFormControlSelect1").change(function() {
    var selectedOption = $(this).find(":selected");
    selectedDeviceId = selectedOption.data("device_id")?.toString() || "";
    sending_data_to_api_log_file_list.device_id = selectedDeviceId;
    // 直接调用create函数,不再手动销毁表格
    create_certain_ipc_log_table(sending_data_to_api_log_file_list);
});

// 修正create_certain_ipc_log_table中的表格初始化逻辑
function create_certain_ipc_log_table(sending_data_to_api_log_file_list) { 
    // ... 原有defaultData和dataToUse逻辑保持不变 ...

    // 统一处理表格实例:先销毁再重建,确保状态干净
    if (certain_ipc_log_table) {
        // 先销毁实例,解除DOM绑定
        certain_ipc_log_table.destroy(true); // true参数会清空表格DOM
        certain_ipc_log_table = null;
    }
    // 重新初始化表格
    certain_ipc_log_table = $("#certain_ipc_log_table_example").DataTable(dataToUse);
}

完整修正代码

$(document).ready(() => {
    const getToken = localStorage.getItem("token");
    var rowData;
    var selectedDeviceId = "";
    newValue = localStorage.getItem("newValue");
    var accountType = localStorage.getItem("acc_type");
    var certain_ipc_log_table;

    let sending_data_to_api_log_file_list = {
        "draw": 1,
        "length": 10,
        "start": 0,
        "device_id": "",
        "search": "",
        "start_datetime": "",
        "end_datetime": ""
    }

    let df = {
        draw: 0,
        columns: ["device_id", "name", "group"],
    };

    $.ajax({
        type: "post",
        url: newValue + '/api/ipc/select',
        async: true,
        headers: {
            "Content-Type": "application/json",
            "accept": "application/json",
            Authorization: "Bearer " + getToken,
        },
        data: JSON.stringify(df),
        success: function(res) {
            var selectElement = document.getElementById("exampleFormControlSelect1");
            selectElement.innerHTML = "";

            var defaultOption = document.createElement("option");
            defaultOption.textContent = "Server";
            defaultOption.value = '';
            defaultOption.dataset.device_id = '';
            selectElement.appendChild(defaultOption);

            res.data.forEach(function(item) {
                var option = document.createElement("option");
                option.textContent = item.group + " - " + item.device_id + " - " + item.name;
                option.dataset.group = item.group;
                option.dataset.device_id = item.device_id;
                option.dataset.name = item.name;
                selectElement.appendChild(option);
            });
        },
        error: function(error) {
            console.trace("ERROR", error);
        }
    });

    // 初始化默认表格
    create_certain_ipc_log_table();

    // 下拉框change事件处理
    $("#exampleFormControlSelect1").change(function() {
        var selectedOption = $(this).find(":selected");
        selectedDeviceId = selectedOption.data("device_id")?.toString() || "";
        sending_data_to_api_log_file_list.device_id = selectedDeviceId;
        // 直接调用创建表格函数,内部统一处理销毁/重建
        create_certain_ipc_log_table(sending_data_to_api_log_file_list);
    });

    function create_certain_ipc_log_table(sending_data_to_api_log_file_list) { 
        let defaultOrder = "desc";
        let defaultOrderColumn = "id";

        newValue = localStorage.getItem("newValue");
        var defaultData = {
            processing: true,
            lengthChange: true,
            serverSide: true,
            lengthMenu: [10,100],

            ajax: {
                url: newValue + '/api/log/files/list',
                type: "POST",
                contentType: 'application/json',
                data: function(d) {
                    d.search = d.search.value;
                    d.order_by = defaultOrder;
                    d.order_column = defaultOrderColumn;
                    return JSON.stringify(d);
                },
                headers: {
                    Authorization: "Bearer " + getToken,
                }
            },

            columns: [
                { data: "filepath", title: "filepath" },
                { data: "filename", title: "filename" },
                { data: "extension", title: "extension" },
                { data: "modified", title: "modified" },
                { data: "size", title: "size" },
                {
                    data: null,
                    title: accountType === "OP" ? "" : "ACTION",
                    visible: accountType !== "OP",
                    render: function(data, type, row) {
                        if (accountType === "OP") {
                            return "";
                        } else {
                            return (
                                '<button type="button" class="btn btn-outline-light btn-edit-delete" id="Edit_Data" data-toggle="modal" data-target="#exampleModal" data-whatever="" onclick="download_certain_ipc_log_to_txt(' + selectedDeviceId + ', \'' + row.filepath + '\', \'' + row.filename + '\')">Download</button>'
                            );
                        }
                    },
                }
            ],

            error: function(xhr, status, error) {
                console.trace("xhr ERROR: ", xhr.responseText);
                console.trace("status ERROR: ", status);
                console.trace("error ERROR: ", error);
            }
        };

        var dataToUse = sending_data_to_api_log_file_list
            ? {
                ...defaultData,
                ajax: {
                    ...defaultData.ajax,
                    data: function(data) {
                        sending_data_to_api_log_file_list.search = data.search.value;
                        return JSON.stringify(sending_data_to_api_log_file_list);
                    },
                },
            }
            : defaultData;

        // 统一处理表格实例:彻底销毁后重建
        if (certain_ipc_log_table) {
            certain_ipc_log_table.destroy(true); // true参数自动清空表格DOM
            certain_ipc_log_table = null;
        }
        certain_ipc_log_table = $("#certain_ipc_log_table_example").DataTable(dataToUse);
    }
});

说明

  • 使用destroy(true)替代手动empty(),DataTable会自动清理表格DOM元素及绑定的事件,避免残留状态导致冲突。
  • 移除冗余的循环检测逻辑,减少不必要的函数调用,从根源避免无限循环触发栈溢出。
  • 统一表格初始化入口,所有表格更新操作都通过create_certain_ipc_log_table处理,避免多处操作实例导致的混乱。

内容的提问来源于stack exchange,提问作者080_coder_from_jap

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 15:30:01