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

AS3循环加载JSON仅存储最后迭代数据的问题排查

多JSON文件加载映射错误问题

需求背景

需要从指定对象中加载多个JSON文件,将每个JSON数据对应到特定标识(比如EMOTE对应emote_frames.json,NPC对应npc.json),存入servicesObj以便后续通过标识获取数据。

定义的标识与文件映射关系:

// 键为servicesObj中数据的标识,值为文件名
static var customServices = {EMOTE: "emote_frames", NPC: "npc"};

实现的处理类代码:

class com.customs.Net.CustomServicesManager {
    
    var customServices, servicesObj, serviceTypeArr, jsonLoader, serviceLoaderArr, serviceTypes, __get__serviceType, arrServicesToLoad, _loadingServiceType;
    public function CustomServicesManager() {
        super();
        trace("Loaded Custom Services Manager");
        servicesObj = {};
        customServices = com.customs.Settings.customServices;
       
    }
    function getServiceData(type) {
        var _local2 = servicesObj[type];
        return (_local2);
    }
    public function get serviceType() {
        serviceTypeArr = [];
        for(var i in customServices) {
            serviceTypeArr.push(i);
        }
        return (serviceTypeArr);
    }
    
    public function serviceTypeVal(val) {
        for(var i in customServices) {
            if(i === val) {
                return (customServices[i]);
            }
        }
    }

    public function loadCustomServices() {
        arrServicesToLoad =  this.__get__serviceType();
        jsonLoader = new com.cp.util.JSONLoader();
        jsonLoader.addEventListener(com.cp.util.JSONLoader.COMPLETE, onCustomServicesJSONLoaded, this);
        loadOngoingServices();
    }
       
   public function loadOngoingServices() {
       if(arrServicesToLoad.length === 0) return (undefined);
        _loadingServiceType = arrServicesToLoad;

       for (var i = 0; i < _loadingServiceType.length; ++i) {
            serviceTypes = _loadingServiceType[i];
            jsonLoader.load(serviceTypeVal(serviceTypes) + ".json");     
        }
    }
 
    public function onCustomServicesJSONLoaded(event) {
        var _local2 = jsonLoader.data;
            servicesObj[serviceTypes] = _local2;
        trace(com.clubpenguin.util.JSONParser.stringify(servicesObj));
      trace(servicesObj["NPC"]["130_npc"].uniqueId);
    }
    

}

问题现象

预期servicesObj中EMOTE和NPC分别对应各自的JSON数据,但实际只有最后加载的NPC数据正确,EMOTE的数据被错误存入NPC键下,无法通过EMOTE标识获取。

输出的servicesObj内容:

{"NPC":[{"disabled":true,"emote_name":"Laughing Face","frame_menu_id":1,"frame_balloon_id":1},{"emote_name":"Smiley","frame_menu_id":2,"frame_balloon_id":2},{"emote_name":"Coffee Cup","frame_menu_id":3,"frame_balloon_id":13},{"emote_name":"Straight Face","frame_menu_id":4,"frame_balloon_id":3},{"emote_name":"Frown","frame_menu_id":5,"frame_balloon_id":4},{"emote_name":"Game","frame_menu_id":6,"frame_balloon_id":18},{"emote_name":"Surprise","frame_menu_id":7,"frame_balloon_id":5},{"emote_name":"Sticking Out Tongue","frame_menu_id":8,"frame_balloon_id":6},{"emote_name":"Popcorn","frame_menu_id":9,"frame_balloon_id":29},{"emote_name":"Wink","frame_menu_id":10,"frame_balloon_id":7},{"emote_name":"Green Sickly Face","frame_menu_id":11,"frame_balloon_id":8},{"emote_name":"Pizza","frame_menu_id":12,"frame_balloon_id":24},{"disabled":true,"emote_name":"Red Angry Face","frame_menu_id":13,"frame_balloon_id":9},{"emote_name":"Sad Face","frame_menu_id":14,"frame_balloon_id":10},{"emote_name":"Ice Cream","frame_menu_id":15,"frame_balloon_id":26},{"emote_name":"Meh Face","frame_menu_id":16,"frame_balloon_id":11},{"emote_name":"Cake","frame_menu_id":17,"frame_balloon_id":28},{"emote_name":"Clover","frame_menu_id":18,"frame_balloon_id":17},{"emote_name":"Heart","frame_menu_id":19,"frame_balloon_id":30},{"emote_name":"Lightbulb","frame_menu_id":20,"frame_balloon_id":12},{"emote_name":"Flower","frame_menu_id":21,"frame_balloon_id":16},{"emote_name":"Skull","frame_menu_id":22,"frame_balloon_id":40},{"emote_name":"Shocked Face","frame_menu_id":23,"frame_balloon_id":41},{"emote_name":"The Nigger","frame_menu_id":24,"frame_balloon_id":42},{"emote_name":"Pink Flower","frame_menu_id":25,"frame_balloon_id":43}]}
{"NPC":{"130_npc":{"isEnabled":true,"itemsObj":{"total_membership_days":0,"is_member":1,"frame":0,"y_corr":100,"x_corr":100,"photo_id":0,"flag_id":0,"feet":0,"hand":0,"body":0,"neck":0,"face":0,"head":0,"colour_id":0},"bitmask":1,"username":"[NPC] Pelican","uniqueId":9000251},"100_npc":{"isEnabled":true,"itemsObj":{"total_membership_days":0,"is_member":1,"frame":0,"y_corr":256,"x_corr":467,"photo_id":0,"flag_id":0,"feet":0,"hand":0,"body":467,"neck":256,"face":26,"head":0,"colour_id":8},"bitmask":1,"username":"[NPC] Bob","uniqueId":9000234}}}

第一部分为EMOTE的正确数据,但被错误存入NPC键下;第二部分NPC数据正确。

问题原因

  1. 单一Loader实例重复使用:循环中用同一个JSONLoader加载多个文件,后一次加载会覆盖前一次的请求状态,导致无法区分回调对应哪个标识。
  2. 变量覆盖问题:循环结束后serviceTypes最终值为NPC,两个请求完成时都会用这个值作为键存入servicesObj,导致EMOTE数据被覆盖到NPC键下。

解决方案

方案1:为每个请求创建独立Loader实例

修改loadOngoingServices和回调方法,为每个请求创建新的JSONLoader,并绑定对应的服务标识:

public function loadOngoingServices() {
    if(arrServicesToLoad.length === 0) return;
    _loadingServiceType = arrServicesToLoad;

    for (var i = 0; i < _loadingServiceType.length; ++i) {
        var serviceType = _loadingServiceType[i];
        var loader = new com.cp.util.JSONLoader();
        loader.serviceType = serviceType; // 将标识绑定到Loader实例
        loader.addEventListener(com.cp.util.JSONLoader.COMPLETE, onCustomServicesJSONLoaded, this);
        loader.load(serviceTypeVal(serviceType) + ".json");
    }
}

public function onCustomServicesJSONLoaded(event) {
    var loader = event.target as com.cp.util.JSONLoader;
    var data = loader.data;
    var serviceType = loader.serviceType;
    servicesObj[serviceType] = data;
    
    trace(com.clubpenguin.util.JSONParser.stringify(servicesObj));
    
    // 检查是否所有服务都加载完成
    var allLoaded = true;
    for(var type in customServices) {
        if(!servicesObj[type]) {
            allLoaded = false;
            break;
        }
    }
    if(allLoaded) {
        trace("所有自定义服务加载完成");
        // 此处可添加加载完成后的逻辑
    }
}

方案2:用闭包保存循环标识(不推荐,不如多实例直观)

如果不想创建多个Loader实例,可在循环中用闭包捕获当前标识,确保回调能拿到正确值:

public function loadOngoingServices() {
    if(arrServicesToLoad.length === 0) return;
    _loadingServiceType = arrServicesToLoad;

    for (var i = 0; i < _loadingServiceType.length; ++i) {
        var serviceType = _loadingServiceType[i];
        // 闭包捕获当前循环的serviceType
        (function(currentType) {
            var tempLoader = new com.cp.util.JSONLoader();
            tempLoader.addEventListener(com.cp.util.JSONLoader.COMPLETE, function(event) {
                var data = tempLoader.data;
                servicesObj[currentType] = data;
                trace(com.clubpenguin.util.JSONParser.stringify(servicesObj));
                
                // 检查全量加载完成
                var allLoaded = true;
                for(var type in customServices) {
                    if(!servicesObj[type]) {
                        allLoaded = false;
                        break;
                    }
                }
                if(allLoaded) {
                    trace("所有自定义服务加载完成");
                }
            }, this);
            tempLoader.load(serviceTypeVal(currentType) + ".json");
        })(serviceType);
    }
}

核心优化点

  • 每个请求绑定专属标识,避免回调时键名错误
  • 确保每个请求状态独立,不被后续请求覆盖
  • 添加全量加载完成检查,方便触发后续业务逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 00:08:01