我正在创建一个Chrome扩展程序,其部分功能是单击网站的链接,该网站本身将打开一个新选项卡,然后我的扩展程序将打印该选项卡。我现在在检测新选项卡的完整性时遇到问题。
我原来的方法是使用
chrome.tabs.onUpdated
并通过检测状态更改为 complete
,代码将继续运行。
async function asyncChkTabLoaded(targetTabID){
return new Promise(resolve => {
chkTabLoaded = function (tabID, tabChanges, tabData) {
if (tabID == targetTabID) {
if ("status" in tabChanges) {
if (tabChanges.status == "complete"){
resolve(tabData);
}
}
}
}
chrome.tabs.onUpdated.addListener(chkTabLoaded);
});
}
await asyncChkTabLoaded(openedTabID);
但是,我发现使用这种方法,部分内容没有完全加载,主要是图像。因此,自动打印将打印一个带有空图像的网站。
complete
并不是真正意义上的完整。
我相信这是由于
tabs.onUpdated
的奇怪属性造成的,即“status
属性将在 "loading"
和 "complete"
之间循环”。 (https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/onUpdated)
我知道我可以使用
image.complete
来检测图像的加载状态。然而,有些图像是 标签包裹在
<svg id="main-svg" preserveAspectRatio="xMidYMid" viewBox="0 0 486 934">
<image x="0.00" y="0.00" width="486.69" height="632.84" image-rendering="-moz-crisp-edges" preserveAspectRatio="none" xlink:href="data:image/png;base64, iVB0KGgoAA..P2YII="></image>
</svg>
而且 svg 元素似乎没有
complete
属性。所以使用 image.complete
可能不完全适合我的情况。
所以我认为使用选项卡窗口的
load
事件作为指导来检测网站内容的完整性是最安全的方法。这是我修改的方法 asyncChkTabLoaded
async function asyncChkTabLoaded(){
return new Promise(resolve => {
console.log("injected onload");
console.log(document.readyState);
sendResolve = function() {
console.log("Window Loaded");
resolve();
}
window.addEventListener("load", sendResolve);
});
}
await chrome.scripting.executeScript({target : {tabId : openedTabID}, func : asyncChkTabLoaded});
然而,
load
事件似乎永远不会被触发,因此承诺永远不会得到解决,await
永远不会,我的代码永远不会继续到下一步打印。document.readyState
始终是 loading
。仅当我将 Window Loaded
移出函数 resolve()
时,才能打印 sendResolve
。
所以我的问题是如何检测新选项卡的选项卡
load
事件?我更喜欢在 resolve
事件中使用 load
,以及 await
resolve
,而不是将所有后续代码放入 load
事件监听器回调中。所以我的代码的可读性更容易,并且更容易在 await
之后添加更多代码。
或者如何检测
tabs.onUpdated
最后一个选项卡状态变化?
或者如何检测 SVG 元素的加载?但这将是解决此问题的最不优选的方法,因为我不确定仍在加载哪些其他不可预测的元素。
非常感谢您的帮助:)
有一个专用且更佳的 chrome.webNavigation API 适合您的目的。具体来说,您正在寻找什么chrome.webNavigation.onCompleted。加载的目标页面将有
frameId == 0
。但请注意,对于 SPA,页面仅加载一次。
chrome.webNavigation.onCompleted.addListener(details => {
// document, including the resources it refers to, is completely loaded and initialized
});