简体   繁体   English

等待异步 function 后不会调用 onload 事件侦听器

[英]onload event listener is not invoked after awaiting on an asynchronous function

My code loads a JSON file that is later used in a function called serverTest .我的代码加载了一个 JSON 文件,该文件稍后在名为serverTest的 function 中使用。

So I have this code:所以我有这段代码:

async function fetchJSON(url) {
    const response = await fetch(url, {
        headers: { accept: "application/json" }
    });
  
    return response.json();
}

const config = await fetchJSON("./config.json");

window.addEventListener("load", function() {
    serverTest(0);
});

const serverList = new Map(Object.entries(config.servers));

function serverTest(index) {
    // code including serverList
}

The problem is that the load event handler does not run.问题是加载事件处理程序没有运行。

Can someone help me?有人能帮我吗?

The problem is that by delaying setting up the event handler until the JSON is loaded, you're missing the load event.问题是,通过延迟设置事件处理程序直到加载 JSON,您会错过load事件。

In the vast majority of use cases (but from the comments, not yours), just remove the event handler entirely:在绝大多数用例中(但来自评论,而不是你的),只需完全删除事件处理程序:

async function fetchJSON (url) {
    const response = await fetch(url, {
        headers: { accept: "application/json" }
    });
    if (!response.ok) {
        throw new Error(`HTTP error ${response.status}`);
    }
    return response.json();
}

const config = await fetchJSON("./config.json");
serverTest(0); // <==== Not wrapped in a `load` event handler

const serverList = new Map(Object.entries(config.servers));

function serverTest(index) {
    //Code including serverList
}

If you make sure your script tag uses type="module" (which yours must do, if you're using top-level await like that), it won't be run until the page HTML is fully loaded and the DOM has been built.如果你确定你的script标签使用type="module" (你必须这样做,如果你使用顶级await ),它不会运行,直到页面 HTML 完全加载并且 DOM 已被加载建成。 (Unless you also have the async attribute on it; details .) (除非你也有async属性; 细节。)

In your use case, waiting for the load event genuinely does make sense, so you'll have to wait until both load and the fetch are done:在您的用例中,等待load事件确实有意义,因此您必须等到loadfetch都完成:

async function fetchJSON (url) {
    const response = await fetch(url, {
        headers: { accept: "application/json" }
    });
    if (!response.ok) {
        throw new Error(`HTTP error ${response.status}`);
    }
    return response.json();
}

// Hook up the `load` event *before* loading `config.json`,
// get a promise for when it fires
const loadPromise = new Promise(resolve => {
    window.addEventListener("load", resolve);
});
// Load and wait for `config.json`
const config = await fetchJSON("./config.json");
// Wait for the `load` event (waits only ***very*** briefly
// if the event has already fired, otherwise waits for it
// to fire)
await loadPromise();
serverTest(0);

const serverList = new Map(Object.entries(config.servers));

function serverTest(index) {
    //Code including serverList
}

Side note: Notice I added a check for ok before calling json .旁注:请注意,我在调用json之前添加了ok检查。 fetch only rejects its promise on network errors, not HTTP errors. fetch仅拒绝其 promise网络错误,而不是 HTTP 错误。 This is (IMHO) a footgun in the fetch API I cover on my old anemic blog here .这是(恕我直言) fetch API 中的一支步兵枪,我在我的旧贫血博客上介绍 过这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM