我的(测试)Chrome扩展中有一段非常简单的代码:
function test()
{
alert("In test!");
}
chrome.tabs.onUpdated.addListener(function(tabid, changeinfo, tab) {
var url = tab.url;
if (url !== undefined) {
test();
}
});
我的问题是,为什么test()
发射两次?更重要的是,我如何让它只火一次?
了解事件调度时的不同状态。我推测,当状态为"加载"或状态为"完成"时,它会被调度一次。如果是这样的话,那么你的问题就会用来解决
function test()
{
alert("In test!");
}
chrome.tabs.onUpdated.addListener(function(tabid, changeinfo, tab) {
var url = tab.url;
if (url !== undefined && changeinfo.status == "complete") {
test();
}
});
我也对此感到困惑,并试图找到答案。只有经过一些实验,我才明白为什么我收到了多个"完整"的更新事件,而我认为这是一个单独的页面"更新"。
如果你的页面有iframe,每个iframe都会触发一个"完整"事件,并冒泡到父内容脚本。因此,如果更复杂的页面有iframe,它们将触发大量onUpdated事件。
当您编写以下代码时:
chrome.tabs.onUpdated.addListener(function(tabid, changeinfo, tab) {
var url = tab.url;
if (url !== undefined) {
test();
}
});
您正在调用addListener
,并告诉它不要立即调用test()
,而是在更新选项卡时。选项卡更新事件由Chrome浏览器本身广播,这反过来又会导致test()
代码运行。
我知道这是旧的,但无论如何。。。这也发生在我身上,也许这能帮助到别人。查看处理程序函数正在接收的Tab对象,我发现favIconUrl属性在两个调用中都不同,所以我想这与此有关,尽管我不知道这背后的原因。
我以为这是一个bug,但经过再三思考和一些测试,我放弃了bug理论。
到目前为止,我所知道的是,如果更改了两个属性,则事件会被触发两次,每次都包含一个属性的changeInfo对象。换句话说,例如,如果更改的属性是状态和收藏夹URL,则
changeInfo = {status:"complete"};
然后在下一次呼叫
changeInfo = {favIconuUrl : ".... whatever ..."};
虽然我不确定为什么我们的代码会触发两次,但我也遇到了类似的问题,这个答案帮了我很多忙。
https://stackoverflow.com/a/49307437/15238857Vaibhav的回答非常聪明,以请求的细节对象的形式结合了验证。在记录details对象时,我注意到一种趋势,即最初的激发的frameId为0,而第二次激发总是其他的。因此,当你有重复的条目时,我喜欢使用if语句来返回并退出,而不是肯定地验证你是否正确提交了URL。我在这里使用onCompleted,但它也应该适用于onUpdated。
chrome.webNavigation.onCompleted.addListener(details => {
//need to make sure that this only triggers once per navigation
console.log(details);
if (details.frameId !== 0) return;
});
我通过在更新时检查选项卡的标题来解决这个问题:
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
var title = changeInfo.title;
if (title !== undefined) {
doSomething();
}
});
两次是由于状态加载一次,状态完成一次。如果您不关心状态,也可以尝试onCreated事件。那只会被炒一次!