Javascript 脚本运行时是否调用setInterval处理程序?
我计划使用setInterval将一个变量简单地设置为false,主循环将检查该变量以停止。示例(注意:这只是一个示例,acutal代码不是一个容易重建的while()循环,而是一个非常复杂的、很长的时间来执行由封闭源代码软件生成的脚本): 然而,它似乎不起作用,至少firefox在一段时间后删除了一个“忙脚本”框。上面的代码有什么问题?如果脚本已经运行,setInterval()可能无法运行,否则?我找不到setInterval()的确切功能规范 我需要这样的东西,因为我已经有一个巨大的(而且执行时间很长)脚本,所以我想我会尝试在一段时间后停止它,然后使用setTimeout()让浏览器呼吸一下,然后继续:因为脚本本身知道它的内部状态,所以它可以从任何点继续,但实际上,修改脚本不是一个选项 如果setInterval无法实现,那么在不修改“long to execute”代码本身的情况下,是否还有其他方法Javascript 脚本运行时是否调用setInterval处理程序?,javascript,setinterval,Javascript,Setinterval,我计划使用setInterval将一个变量简单地设置为false,主循环将检查该变量以停止。示例(注意:这只是一个示例,acutal代码不是一个容易重建的while()循环,而是一个非常复杂的、很长的时间来执行由封闭源代码软件生成的脚本): 然而,它似乎不起作用,至少firefox在一段时间后删除了一个“忙脚本”框。上面的代码有什么问题?如果脚本已经运行,setInterval()可能无法运行,否则?我找不到setInterval()的确切功能规范 我需要这样的东西,因为我已经有一个巨大的(而且
谢谢 问题在于Javascript是单线程的。重写
while
循环以使用setInterval
本身,一切都应该正常,因为您将在每个循环结束时释放线程
如果setInterval无法实现,那么在不修改“long to execute”代码本身的情况下,是否还有其他方法
一种可能是将其设置为一个线程,而不是尝试在UI线程上使用它。尽管人们一再这样说,JavaScript不是单线程的(JavaScript,一种语言,在这个问题上是沉默的),甚至在浏览器上也不是了。在浏览器环境中,有一个主UI线程,但您可以生成其他工作线程(web工作线程)。工作者和主UI代码可以通过postMessage
/onmessage
进行通信
下面是一个网络工作者的例子。此页面在UI线程上使用JavaScript启动web worker,它在单独的线程上运行。worker运行10秒,忙于更新计数器(这只是为了模拟一个长时间运行、计算密集的过程),并每秒向UI线程发送更新:
主页:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Worker Example</title>
<style type="text/css">
body {
font-family: sans-serif;
}
</style>
<meta charset="UTF-8">
</head>
<body>
<script>
(function() {
var worker = new Worker("worker.js");
worker.onmessage = function(e) {
display("Worker says " + e.data);
};
display("Starting worker");
worker.postMessage("start");
function display(msg) {
var p = document.createElement('p');
p.innerHTML = String(msg);
document.body.appendChild(p);
}
})();
</script>
</body>
</html>
工人示例
身体{
字体系列:无衬线;
}
(功能(){
var-worker=new-worker(“worker.js”);
worker.onmessage=函数(e){
显示(“工人说”+e.数据);
};
显示(“起始工人”);
worker.postMessage(“开始”);
功能显示(msg){
var p=document.createElement('p');
p、 innerHTML=字符串(msg);
文件.正文.附件(p);
}
})();
worker.js:
this.onmessage = function(e) {
var counter, lastUpdate, now;
if (e.data === "start") {
// Loop without yeilding for 10 seconds, sending updates
// to the UI every second.
start = lastUpdate = Date.now();
counter = 0;
do {
++counter;
now = Date.now();
if (now - lastUpdate > 1000) {
lastUpdate = now;
this.postMessage(counter);
}
}
while (now - start < 10000);
this.postMessage("Done");
}
};
this.onmessage=函数(e){
var计数器,最近更新,现在;
如果(如数据==“开始”){
//循环10秒钟,不显示yeilding,发送更新
//每隔一秒钟就可以打开UI。
start=lastUpdate=Date.now();
计数器=0;
做{
++计数器;
now=Date.now();
如果(现在-最新更新>1000){
lastUpdate=now;
这是邮政信息(柜台);
}
}
而(现在-开始<10000);
本.邮递信息(“完成”);
}
};
(您不需要让工人等待消息启动,但这是相当常见的)。
< P>您应该考虑使用或编写异步代码。 或者你可以修改你的代码var running = true;
var past = Date.now();
while (running) {
// do heavy calculations ...
if ((Date.now() - past) > 10) {
running = false;
}
}
当然,阻塞循环不是个好主意,但我不认为有什么好方法可以满足需求:
如果setInterval无法实现,那么在“long to execute”代码本身中是否有替代方法,而不进行任何修改
JavaScript在单线程事件循环中运行。这意味着当您的代码正在运行时,其他代码无法运行。这就是您的回调无法执行的原因 您还可以通过将while(运行)设置为异步来解决这个问题。考虑以下事项:
var running = true;
var monitor = setInterval(function () {
if (running) {
console.log("Stopping now!");
running = false;
clearInterval(monitor);
}
}, 100);
var work = setInterval(function() {
if (running) {
// do something
} else {
clearInterval(work);
}
}, 1);
别忘了打电话给clearInterval 循环时应使用setTimeout或setInterval。JS在单线程中运行,所以无限循环将冻结您的浏览器
var running = true;
setInterval(function(){
if(running){
console.log('Stopping now!');
running = false;
}
}, 100);
(function loop(){
// Do yours loop stuff
if( running ){
setTimeout(loop, 0);
}
})();
…但实际上,这不是修改脚本的选项。嗯,有个问题。是的,它是。。。因为它是由一个软件生成的,而且不是一直都是一样的。该软件是一个封闭源代码的东西:(@LGB:while循环是原始脚本的一部分,对吗?好吧,我的错,它只是一个非常愚蠢的示例/测试脚本,而不是实际的(非常庞大和复杂)。请阅读我为T.J.Crowder的答案所做的评论。很抱歉造成混淆。“或者你可以修改你的代码。”等待10毫秒的繁忙循环有什么意义?Worker的建议很好,但下面的代码示例不是。@filmor:我的示例旨在测试我是否可以这样做的理论。如果我的想法可行,我想尝试一下这个简单的测试示例。它没有。谢谢,web Worker似乎是一个很好的解决方案。尽管在我的示例中,我编写了一个simpe while()循环很容易重建,实际执行的长脚本不是这样的,也不太可能修改它,因为它是一个封闭源代码软件生成的JS代码,只发出JS文件(如果再次生成该文件,甚至不一样)。也许把它放到工作线程中会有效果,我会试试。@LGB:啊,我明白了。我以为
循环在等待另一个代码完成(不起作用:-))。我已经删除了第一段。最好的,
var running = true;
setInterval(function(){
if(running){
console.log('Stopping now!');
running = false;
}
}, 100);
(function loop(){
// Do yours loop stuff
if( running ){
setTimeout(loop, 0);
}
})();