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

如何控制JavaScript Promise执行顺序,实现子对象优先初始化?

问题:控制嵌套对象反序列化的初始化顺序

场景与现有代码

我们需要反序列化包含type键的JSON对象:

  • type值为字符串,对应加载同名JS文件(如type="a"则加载a.js,文件内包含初始化函数a_init)
  • 对象可能包含subobjects键,其值为对象数组,嵌套对象需按相同规则处理

现有实现代码如下:

var files = [];

function load(obj) {
  if (!!obj["type"]) {
    let type       = obj.type;
    let subobjects = obj.subobjects;
    let promise    = new Promise(function(resolve) {
                         let script = document.createElement("script");
                         script.setAttribute("src", type + ".js");
                         script.addEventListener("load",resolve);
                         document.head.appendChild(script);
                     });
    promise.then(function() {
        if (!files.includes(type)) {
          files.push(type);
          if (subobjects instanceof Array) {
            for (element of subobjects) {
              load(element);
            }
          }
          let func = window[type + "_init"];
          if (typeof(func) =="function") {
            func(obj);
          }
        }
    });
  }
}

测试用例与当前问题

测试对象:

{ "type": "a",
  "data": "foo",
  "subobjects": [
      { "type": "b",
        "data": "1"
      }
  ]
}

当前输出(a_init和b_init仅输出测试消息):

This is A
This is B

我们需要子对象先完成初始化,即输出顺序为:

This is B
This is A

当前代码中嵌套调用load仅生成新Promise,但不会等待子对象的异步操作完成就执行当前对象的init,导致顺序不符合预期。

解决方案:基于Promise的顺序控制

修改load函数,让它返回Promise,确保先完成所有子对象的初始化,再执行当前对象的init:

var files = [];

function load(obj) {
  // 没有type的直接返回已完成的Promise
  if (!obj["type"]) return Promise.resolve();

  let type = obj.type;
  let subobjects = obj.subobjects;

  // 1. 加载当前类型的脚本
  const loadScriptPromise = new Promise(resolve => {
    const script = document.createElement("script");
    script.src = `${type}.js`;
    script.addEventListener("load", resolve);
    document.head.appendChild(script);
  });

  // 2. 等待脚本加载完成后,处理子对象并执行当前init
  return loadScriptPromise.then(() => {
    // 避免重复加载同类型脚本
    if (files.includes(type)) return;
    files.push(type);

    // 处理子对象:等待所有子对象的load操作全部完成
    const subPromises = (subobjects instanceof Array) 
      ? subobjects.map(element => load(element)) 
      : [];

    // 3. 所有子对象初始化完成后,再执行当前对象的init
    return Promise.all(subPromises).then(() => {
      const func = window[`${type}_init`];
      if (typeof func === "function") {
        func(obj);
      }
    });
  });
}

关键修改点

  1. 让load返回Promise:这样可以通过Promise.all等待所有子对象的异步操作完成
  2. 调整执行顺序:脚本加载完成后,先触发所有子对象的load并等待它们全部完成,最后再执行当前对象的init
  3. 避免重复加载:保持原有的files数组逻辑,防止同一类型脚本重复加载

调用时如果需要等待整个初始化流程完成,可以使用:

load(testObj).then(() => {
  console.log("所有对象初始化完成");
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 17:40:15