JavaScript Promise 和同步行为

问题描述 投票:0回答:1

我正在尝试反序列化一个 JSON 对象,该对象有一个

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

输出为:

This is A
This is B

(功能

a_init
b_init
仅显示一条消息用于测试目的。)

我的问题是我希望子对象在外部对象之前初始化,因此

b_init
将在
a_init
之前完成以给出以下输出:

This is B
This is A

但是当然,对

load
的嵌套调用只是创建一个新的 Promise,然后在新的 Promise 之前完成。

有什么方法可以强制同步来控制事件的顺序吗?

javascript promise synchronous
1个回答
0
投票

您应该将

load
函数转换为
async
并在其内部
await
以实现承诺以及完成递归调用。

var files = [];

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;
    
    if (!files.includes(type)) {
      files.push(type);
      if (subobjects instanceof Array) {
        for (element of subobjects) {
          await load(element);
        }
      }
      let func = window[type + "_init"];
      if (typeof(func) == "function") {
        func(obj);
      }
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.