我正在try 解析一个JSON对象,它有一个type键,其值是一个字符串;如果类型是"a",则对象类定义在"a.js"中,并且此文件包含一个初始化函数a_init.可能有一个subobjects键,其值是一个对象array.如果是这样,这些嵌套对象应该以相同的方式处理.

我拥有的代码如下所示:

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"
      }
  ]
}

输出为:

This is A
This is B

(函数a_initb_init仅显示用于测试目的的消息.)

我的问题是,我希望在外部对象之前初始化子对象,因此b_init将在a_init之前完成,以提供以下输出:

This is B
This is A

但是当然,对load的嵌套调用只是创建一个新的promise,然后在新的promise之前完成.

这里有没有办法强制同步性来控制事件的顺序?

推荐答案

您应该将load函数转换为async,并在其中转换为await,以完成Promise和递归调用.

var files = [];

// using an async function here so that we can 
// use await inside it, but also so that we can
// await the whole function (it is recursively called
// and we want the recursions to fully complete before 
// continuing)
async function load(obj) {
  if (!!obj["type"]) {
    let type = obj.type;
    let subobjects = obj.subobjects;
    const promise = new Promise(function(resolve) {
      let script = document.createElement("script");
      script.setAttribute("src", type + ".js");
      script.addEventListener("load", resolve);
      document.head.appendChild(script);
    });
    
    await promise; // wait for the script to be loaded 
    
    if (!files.includes(type)) {
      files.push(type);
      if (subobjects instanceof Array) {
        for (element of subobjects) {
          // await for the nested object to completely run 
          // before continuing. This will go deep first

          await load(element);
        }
      }
      let func = window[type + "_init"];
      // we reach this place only after all nested objects
      // completed.
      if (typeof(func) == "function") {
        func(obj);
      }
    }
  }
}

Javascript相关问答推荐

将数据从strapi提取到next.js,但响应延迟API URL

确定MutationRecord中removedNodes的索引

如何为GrapesJS模板编辑器创建自定义撤销/重复按钮?

Klaro与Angular的集成

从实时数据库(Firebase)上的子类别读取数据

在网页上添加谷歌亵渎词

如何控制Reaction路由加载器中的错误状态?

在FAQ Accodion应用程序中使用React useState时出现问题

如何在DYGRAPS中更改鼠标事件和键盘输入

未捕获的运行时错误:调度程序为空

当我点击一个按钮后按回车键时,如何阻止它再次被点击

如何修复错误&语法错误:不能在纯react 项目中JEST引发的模块&之外使用导入语句?

使用API调用的VUE 3键盘输入同步问题

react 路由DOM有条件地呈现元素

如何在TransformControls模式下只保留箭头进行翻译?

在HTML5画布上下文中使用putImageData时,重载解析失败

TypeORM QueryBuilder限制联接到一条记录

在Press Reaction本机和EXPO av上播放单个文件

如何在加载页面时使锚定标记成为焦点

material UI自动完成全宽