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

setInterval调用ajax报too much recursion递归错误排查与解决

问题记录与解决

大家好:

更新说明

我已通过变通方案解决该问题,将原有循环查询子表数据写入数组的逻辑:

$numcflsinfpres = dbquery('SELECT fs_sub_id,fs_sub_cnt FROM '.$db_table['moveable_subs'].' WHERE fs_moveable_id='.$numcflinfparr['moveable_id']);
while($numcflsarr = mysqli_fetch_assoc($numcflsinfpres)) {
    array_push($numcflinfparr['moveable_subs'],$numcflsarr);
}

封装为独立函数,改用如下调用方式实现:

array_push($numcflinfparr['moveable_subs'], get_babylon_sub_object_data($numcflinfparr['moveable_id']));

问题原描述

我需要通过jQuery的$.ajax方法接收PHP端mysqli_fetch_assoc返回的数组,实现前端JS对象的数据更新。该功能原本运行正常,但在添加setInterval配置每15分钟自动更新数据后,控制台抛出 Uncaught (in promise) InternalError: too much recursion 错误。

我曾尝试将原for..of全量遍历更新逻辑改为仅针对指定objectID调用单个对象更新接口,仍未解决问题,报错定位在$.ajax语句所在行。经排查,报错在执行PHP函数中向数组push关联数组的逻辑时触发,对应函数代码如下:

function get_babylon_object_data($user,$id) {
    $envobjects = array();
    $envobjectsarr = mysqli_fetch_assoc(dbquery('SELECT object_id,object_user_id FROM '.$db_table['objects'].' WHERE object_id='.$id));
    if(($envobjectsarr['object_id'] ?? 0)>0) {
        $envobjectsarr['object_moveables'] = array();
        if($envobjectsarr['object_user_id']==$user['id']) {
            $numcflinfpres = dbquery('SELECT moveable_id,moveable_user_id,moveable_object_id,moveable_subobject_id FROM '.$db_table['moveable'].' WHERE moveable_object_id='.$envobjectsarr['object_id']);
            while($numcflinfparr = mysqli_fetch_assoc($numcflinfpres)) {
                $numcflinfparr['moveable_subs'] = array();
                $numcflsinfpres = dbquery('SELECT fs_sub_id,fs_sub_cnt FROM '.$db_table['moveable_subs'].' WHERE fs_moveable_id='.$numcflinfparr['moveable_id']);
                while($numcflsarr = mysqli_fetch_assoc($numcflsinfpres)) {
                    array_push($numcflinfparr['moveable_subs'],$numcflsarr);
                }
                array_push($envobjectsarr['object_moveables'],$numcflinfparr);
            }
        }
        $envobjectsarr['object_subobjects'] = array();
        $envsubobjectsres = dbquery('SELECT * FROM '.$db_table['subobjects'].' WHERE subobject_object_id='.$envobjectsarr['object_id']);
        while($envsubobjectsarr=mysqli_fetch_assoc($envsubobjectsres)) {
            $envsubobjectsarr['subobject_moveables'] = array();
            if($envsubobjectsarr['subobject_user_id']==$client['id']) {
                $numflinfpres = dbquery('SELECT moveable_id,moveable_user_id,moveable_object_id,moveable_subobject_id FROM '.$db_table['moveable'].' WHERE moveable_subobject_id='.$envsubobjectsarr['subobject_id']);
                while($numflinfparr = mysqli_fetch_assoc($numflinfpres)) {
                    $numflinfparr['moveable_subs'] = array();
                    $numflsinfpres = dbquery('SELECT fs_sub_id,fs_sub_cnt FROM '.$db_table['moveable_subs'].' WHERE fs_moveable_id='.$numflinfparr['moveable_id']);
                    while($numflsinfparr = mysqli_fetch_assoc($numflsinfpres)) {
                        array_push($numflinfparr['moveable_subs'], $numflsinfparr);
                    }
                    array_push($envsubobjectsarr['subobject_moveables'], $numflinfparr);
                }
            }
            $envobjectsarr['object_subobjects'][$envsubobjectsarr['subobject_object_pos']] = $envsubobjectsarr;
        }
        $envobjects[$id] = $envobjectsarr;
    }
    return $envobjects[$id] ?? array('object_id'=>$id);
}

错误调用栈

完整错误调用栈显示jQuery的isPlainObject、extend方法出现上百次递归调用:

aUpdateObject Updater.js:15
updateObject Updater.js:8
interval Updater.js:35
(Async: setTimeout handler)
interval Updater.js:32
(Async: setInterval handler)
initUpdater Updater.js:30
setup Central.js:29
onFinish Central.js:28
_decreaseWaitingTasksCount assetsManager.ts:1143
done assetsManager.ts:1176
_onDoneCallback assetsManager.ts:168
run assetsManager.ts:117
runTask assetsManager.ts:389
successHandler sceneLoader.ts:756
ImportMesh sceneLoader.ts:792
(Async: promise callback)
ImportMesh sceneLoader.ts:789
dataCallback sceneLoader.ts:552
GLTFFileLoader glTFFileLoader.ts:652
LoadFile fileTools.ts:343
onReadyStateChange fileTools.ts:457
(Async: EventListener.handleEvent)
addEventListener webRequest.ts:138
retryLoop fileTools.ts:482
requestFile fileTools.ts:485
RequestFile fileTools.ts:519
LoadFile fileTools.ts:342
_loadFile scene.ts:4416
_loadFile glTFFileLoader.ts:866
loadFile glTFFileLoader.ts:647
manifestChecked sceneLoader.ts:582
Database database.ts:69
OfflineProviderFactory database.ts:11
_LoadData sceneLoader.ts:603
ImportMesh sceneLoader.ts:765
runTask assetsManager.ts:379
run assetsManager.ts:114
_runTask assetsManager.ts:1194
load assetsManager.ts:1248
createScene Central.js:36
default Central.js:10
<anonym> index.js:5
InnerModuleEvaluation self-hosted:2325
evaluation self-hosted:2286

>jquery 128
    isPlainObject
    ... (127x?) extend

相关代码文件

Updater.js

export class Updater {
    constructor(main) {
        this.objects = {};
        this.upobjects = {};    // 更新请求存储对象
    }

    updateObject(id) {
        if(!this.upobjects[id]) {   // 无对应进行中的更新请求时才触发
            this.aUpdateObject(id);
            this.upobjects[id] = id;    // 标记请求已发起
        }
    }

    async aUpdateObject(id) {
        const aUpdater = this;  // 缓存上下文供回调使用
        $.ajax({
        type: 'post',
        url: 'path/to/updateData.php',
        dataType:'json',
        data: {user:aUpdater.data, id:id},
        success : function (result) {
            // 依次更新数据、3D模型、UI
        },
        error: function(data) {
            console.log('error');
            console.log(data);
        }
        });
    }

    initUpdater() {
        const updater = this;
        this.interval = window.setInterval(function(){  // 每15分钟执行一次全量更新
            let count = 1;
            for(const object of Object.values(updater.objects)) {   // 遍历所有对象
                setTimeout(function(){
                    updater.updateObject(object.id);    // 触发单个对象更新
                },count*1000);

                count++;
            }
        }, 900000);
    }
}

Central.js

// 引入BABYLON库
// 引入Updater.js

export default class {
    constructor() {
        this.canvas = document.getElementById('renderCanvas');  // 渲染画布
        this.engine = new BABYLON.Engine(this.canvas, true, { stencil: true }); // 初始化渲染引擎
    
        this.scene = new BABYLON.Scene(this.engine);    // 初始化场景
        this.createScene();
    }

    createScene() {
        this.assetManager = new BABYLON.AssetsManager(this.scene);  // 模型加载器
        this.updater = new Updater(this);   // 初始化对象更新管理器

        // 此处填充this.updater.objects数据,准备模型加载逻辑

        const central = this;
        window.addEventListener('resize', function() {
            central.engine.resize()
        });

        this.assetManager.onProgress = (remainingCount, totalCount, task) => {
            console.log(remainingCount, totalCount, task.name);
        }

        this.assetManager.onFinish = (tasks) => {   // 所有3D模型加载完成后触发
            this.setup();

            this.engine.runRenderLoop(function() {
                central.scene.render(); // 启动场景渲染循环
            });
        };
    
        this.assetManager.load();   // 开始加载3D模型
    }

    setup() {
        this.updater.initUpdater();
    }
}

index.js

// 引入BABYLON库
// 引入Central.js

if (BABYLON.Engine.isSupported()) {
    window.central = new Central(); // 初始化应用
}

updateData.php

<?PHP
ini_set('MAX_EXECUTION_TIME', 1800);
define('CENTRAL_ROOT_DIR','..');
include_once(CENTRAL_ROOT_DIR.'/path/to/funcs.php');  // 包含get_babylon_object_data()方法
include_once(CENTRAL_ROOT_DIR.'/path/to/config.php');  // 包含数据库配置      
dbconnect();  // 连接MySQL数据库
$conf = get_all_config();  // 获取应用配置
include_once(CENTRAL_ROOT_DIR.'/path/to/definitions.php');  // 包含全局常量定义

function get_babylon_object($user,$id) {
    return json_encode(get_babylon_object_data($user,$id)); // 方法通过mysqli_fetch_assoc查询数据库,更新并返回用户关联数组
}
echo get_babylon_object($_POST['user'] ?? array(),$_POST['id'] ?? 0);

dbclose();  // 关闭数据库连接
?>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 06:42:37