Web 扩展 - document.getElementById 在执行异步方法之前返回 null

Web Extension - document.getElementById returning null before execution of async method

我有一个 chrome/firefox 网络扩展。单击时,此 Web 扩展会在网站的 HTML 文件。它通过使用内容脚本来做到这一点。

下面是内容脚本中 onMessage 侦听器的简化代码:

    browser.runtime.onMessage.addListener((message) => {

    var iFrame = document.createElement("iFrame");
    iFrame.id = "contentFrame";
    iFrame.style.cssText = "width: 100%; height: 100%; border: none;";
    iFrame.src = browser.extension.getURL("inject.html");

    var boxDiv = document.createElement("div");
    boxDiv.style.cssText = "background: white; box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 9px 8px; height: 100%; left: calc(100% - 390px); position: fixed; top: 0px; width: 390px; z-index: 1;"

    var zeroDiv = document.createElement("div");
    zeroDiv.style.cssText = "position: fixed; width: 0px; height: 0px; top: 0px; left: 0px; z-index: 2147483647;";

    var outerDiv = document.createElement("div");

    boxDiv.appendChild(iFrame);
    zeroDiv.appendChild(boxDiv);
    outerDiv.appendChild(zeroDiv);
    document.body.appendChild(outerDiv);

    var closeButton1 = document.getElementById("contentFrame").contentWindow.document.getElementById("close-btn");
    console.log("Close Button1 Fetched: " + closeButton1);

    //closeButton.onClick = function () {
    //  console.log("Close button clicked");
    //}

    returnSummary(message.summaryLength, message.targetURL).then(summary => {

        var closeButton2 = document.getElementById("contentFrame").contentWindow.document.getElementById("close-btn");
        console.log("Close Button2 Fetched, Setting Listener: " + closeButton2);

        closeButton2.onClick = function() {
            console.log("Close button clicked");
        }
    });
});

对于上下文 - returnSummary 是一个包含一堆获取请求的异步函数。

奇数部分如下:

第一条日志语句:console.log("Close Button1 Fetched: " + closeButton1); returns null,

但是第二个日志语句:console.log("Close Button2 Fetched, Setting Listener: " + closeButton2); returns [object HTMLButtonElement].

因此,document.getElementbyId 似乎在异步请求完成后工作。为什么会发生这种情况,如何尽早检索 ID 为 close-btn 的 HTML 元素的值? (我想在按钮上设置一个 onClick 侦听器)。

另一个奇怪的问题是,即使我设置了对象closeButton2onClick方法,点击"close button"也没有任何反应。但是,这不是 post 的主要问题。

这里还有"inject.html"里面的HTML,(最上面的大多只是CSS):

<!DOCTYPE html>
<html style="height: 100%">
<!-- TODO: Create Loader -->

<head>
    <link href="https://fonts.googleapis.com/css?family=Nunito:700,800" rel="stylesheet">
    <style>
    .btn {
        width: 25%;
        height: 35px;
        cursor: pointer;
        border: 2px solid currentcolor;
        border-radius: 5px;
        background-color: white;
        color: dodgerblue;
        font-family: 'Nunito', sans-serif;
        font-weight: 800;
        font-size: 16px;
        text-align: center;
    }

    .btn:hover {
        background: #2196F3;
        color: white;
    }

    #summary {
        width: 100%;
        height: 90%;
        min-height: calc(100% - 75px);
        max-height: calc(100% - 55px);
        margin: 0;
        padding-left: 8px;
        padding-right: 8px;
        box-sizing: border-box;
        overflow-y: auto;
        font-family: 'Nunito', sans-serif;
        font-weight: 700;
        font-size: 14px;
        color: #52575C;
        white-space: pre-line;
    }
    </style>
</head>

<body style="height: 100%; margin: 0;">
    <div style="width: 100%; height: 10%; min-height: 55px; max-height: 75px; display: flex; flex-direction: row; flex-wrap: nowrap; justify-content: space-evenly; align-items: center;">
        <button class="btn" id="close-btn">Close</button>
        <button class="btn" id="copy-btn">Copy</button>
    </div>
    <p id="summary"/> Loading Summary...
    </p>
</body>

</html>

您无法访问该元素的原因是 iframe 加载是一个异步过程。因此,您可以使用类似 :

iframe.onload = function() { // do something here ; }

另一种方法是使用轮询直到元素加载完毕,显然您需要在那里添加超时检查。当您处理外部 DOM 并且您不确定它何时加载时,这尤其有用。