Javascript 通过网页清除内容脚本设置的间隔

Javascript 通过网页清除内容脚本设置的间隔,javascript,google-chrome-extension,Javascript,Google Chrome Extension,在我的chrome扩展中,我在内容脚本中有一个setInterval,它每3秒钟检查一次网页中的更改 setInterval(detectChange, 3000) function detectChange(){ ... } 这对除一个()之外的所有网站都非常有效。网页脚本以某种方式清除了通过内容脚本设置的间隔 我考虑将setInterval放在后台脚本中,并在每个间隔向内容脚本发送消息。但这需要我跟踪所有运行内容脚本的选项卡,这似乎不是一个好主意 请告诉我是否有办法。可取消的任务

在我的chrome扩展中,我在内容脚本中有一个setInterval,它每3秒钟检查一次网页中的更改

setInterval(detectChange, 3000)

function detectChange(){
    ...
}
这对除一个()之外的所有网站都非常有效。网页脚本以某种方式清除了通过内容脚本设置的间隔

我考虑将setInterval放在后台脚本中,并在每个间隔向内容脚本发送消息。但这需要我跟踪所有运行内容脚本的选项卡,这似乎不是一个好主意


请告诉我是否有办法。

可取消的任务调度程序(
setTimeout
setInterval
requestAnimationFrame
等)显然与文档相关。尽管内容脚本的脚本执行上下文与页面隔离,但文档不是

一个站点清除不是由站点本身创建的计时器似乎有点奇怪。您可以尝试调试该问题,并通过覆盖
clearTimeout
/
cleartimeoval
方法来检查站点清除计时器的原因

下面是一个捕获清除脚本本身未安装的计时器的代码的示例:

//在文档开始时运行此内容脚本
var s=document.createElement('script');
s、 textContent='('+函数(){
var clearTimeout=window.clearTimeout;
var setTimeout=window.setTimeout;
var setInterval=window.setInterval;
//注意:此句柄列表永远不会被清除,因为它是
//记录计时器完整历史的唯一方法。
var句柄=[];
window.setTimeout=函数(){
var handle=setTimeout.apply(这是参数);
如果(手柄)手柄。推(手柄);
返回手柄;
};
window.setInterval=函数(){
var handle=setInterval.apply(这是参数);
如果(手柄)手柄。推(手柄);
返回手柄;
};
window.clearTimeout=window.clearInterval=函数(句柄){
清除超时(句柄);
if(handle&&handles.indexOf(handle)=-1){
//打印堆栈跟踪以进行调试
console.trace('Cleared non-owned timer!');
//或者触发断点,以便跟踪调用
//堆栈以标识哪个调用方负责
//清除未知计时器。
调试器;
}
};
} + ')();';
(document.head | | document.documentElement)。追加子项;
s、 删除();
如果这表明站点有缺陷,并且(例如)清除了每个偶数计时器,那么只需调用setTimeout两次即可解决问题

例如:

Promise.race([
新承诺(功能(解决){
setTimeout(解析,3000);
}),
新承诺(功能(解决){
setTimeout(解析,3000);
});
}).然后(函数(){
//有人开枪了吗
});
如果其他一切都失败了。。。 如果站点以不可预知的方式清除计时器,您可以尝试使用其他异步方法或事件来安排任务,并测量调用之间的时间。当某个时间过去后,只需触发回调。例如,使用(通常每秒调用几次):

函数调度任务(回调,超时){
超时=+超时| | 0;
var start=performance.now();
函数onDone(时间戳){
if(timestamp-start>=timeout)回调();
else请求动画帧(onDone);
}
请求动画帧(onDone);
}
//用法示例:
console.time('testScheduler');
scheduleTask(函数(){
console.timeEnd('testScheduler');
}, 1000);

或者插入一个
并在框架的上下文中创建计时器。

您所描述的是不可能的。除非页面导航到别处,否则页面无法触及您的内容脚本的上下文。需要更多调试。这也是我的理解。但我找不到任何其他解释。页面不会导航到别处,因为,其他部分内容脚本仍然有效,例如消息侦听器和事件处理程序。感谢您的回复。我按照您的建议进行了调试,得到了以下结果:
清除了非自有计时器![VM54028:1]window.clearTimeout.window.clearInterval[ImageLoader.f79C22BA20B9F32EC63488859B91348.js:87]R.Component.create.onload[jquery-1.8.3.c2901e3fdd932a1fc29794aafece65e5.js:3058]jquery.event.dispatch[jquery-1.8.3.c2901e3fdd932a1fc29494aafece65e5.js:2676]jquery.event.add.elemData.handle.eventHandle[(索引):129]nrWrapper
看起来,页面中的某些ImageLoader代码正在清除我的间隔!我使用requestAnimationFrame尝试了scheduledTask函数。它也不起作用,回调函数只运行一次。@Samik回调函数应该只运行一次,因为该方法类似于
setTimeout
。调用
scheduledTask
a如果你想安排一个周期性的任务,比如
setInterval
,那么在调用回调时获得收益。对!我还是有一些问题。最后,我接受了你的最后一个建议(使用):
$(“”).css('display','none')。appendTo('body')[0]。contentWindow.setInterval(detectChange,3000)
。它工作得很好。再次感谢您的帮助。在CS/网页分离方面,这是一个混乱的问题。感谢您参与这个主题。