javascript停止一个无限循环
javascript stop an infinite loop
这是node.js.
我有一个函数,如果满足几个条件,它可能会变成一个无限循环。不受信任的用户设置了这些条件,因此出于这个问题的目的,请假设无限循环是不可修复的。
我仍然需要一种方法来阻止无限循环。
以下是我尝试做的一些示例代码:
var infiniteloop = false;
var condition = true
function loop () {
while (condition) {
console.log('hi')
if (infiniteloop) {
condition = false
console.log('oh last one')
}
}
}
loop()
因此,基于我正在尝试做的事情,有几个问题。
- 如果
infiniteloop
变量设置为true,循环将停止,对吗 - 如何检测无限循环?每隔3秒钟检查一次就好了
- 如果
infiniteloop
变量在同一进程中,则在循环时不能更改该变量。我必须将变量存储在不同的过程中 - 任何检测到无限循环的东西都需要生活在不同的过程中?理想情况下,同样的过程会很好,但什么有效
谢谢你的帮助。
基于其他方案组合的解决方案:
function Worker()
{
this.MaxIterations = 1000000;
this.Enabled = true;
this.condition = true;
this.iteration = 0;
this.Loop = function()
{
if (this.condition
&& this.Enabled
&& this.iteration++ < this.MaxIterations)
{
console.log(this.iteration);
setTimeout(this.Loop.bind(this),0);
}
};
this.Stop = function()
{
this.Enabled = false;
};
}
var w = new Worker();
setTimeout(w.Loop.bind(w), 0);
setTimeout(w.Stop.bind(w), 3000);
不确定这是否是最佳的,但应该如预期的那样工作。
使用setTimeout恢复循环允许主node.js事件循环处理其他事件,如w.Stop.
Infinity在这种情况下取决于循环的最大迭代次数。此代码阻止了JavaScript的单线程特性,因此除非使用web Worker,否则无论如何都会锁定所有内容。最好不要每x秒检查一次,因为这段代码无论如何都会阻止间隔或超时的执行,而应该将其作为循环迭代的最大阈值放在循环中。
var infiniteloop = false;
var condition = true;
var loopCounter = 1;
var maxLoopIterations = 1000;
function loop () {
while (condition) {
console.log('hi');
infiniteLoop = (loopCounter >= maxLoopIterations);
if (infiniteloop) {
condition = false;
console.log('oh last one');
break;
}
loopCounter++;
}
}
实际上,您不需要停止无限循环。使用setImmediate
例如:
var immediateId;
function loop () {
console.log('hi');
immediateId = setImmediate(loop);
}
loop();
这段代码会一直说hi,直到你停止它。
//stop the loop:
clearImmediate(immediateId);
为什么使用setImmediate
- 内存消耗保持较低,不会引起内存韭菜
- 不会抛出CCD_ 5
- 性能良好
此外,
我创建了这个模块来轻松管理无限循环:
var util = require('util');
var ee = require('events').EventEmitter;
var Forever = function() {
ee.call(this);
this.args = [];
};
util.inherits(Forever, ee);
module.exports = Forever;
Forever.prototype.add = function() {
if ('function' === typeof arguments[0]) {
this.handler = arguments[0];
var args = Array.prototype.slice.call(arguments, 1);
if (args.length > 0) {
this.args = args;
}
} else {
this.emit('error', new Error('when using add function, the first argument should be a function'));
return 0;
}
return this;
};
Forever.prototype.run = function() {
var handler = this.handler;
var args = this.args;
var that = this;
this._immediateId = setImmediate(function() {
if (typeof handler === 'function') {
switch (args.length) {
// fast cases
case 0:
handler.call(that);
that.run();
break;
case 1:
handler.call(that, args[0]);
that.run();
break;
case 2:
handler.call(that, args[0], args[1]);
that.run();
break;
// slower
default:
handler.apply(that, args);
that.run();
}
} else {
//no function added
that.emit('error', new Error('no function has been added to Forever'));
}
});
};
Forever.prototype.stop = function() {
if (this._immediateId !== null) {
clearImmediate(this._immediateId);
} else {
this.emit('error', new Error('You cannot stop a loop before it has been started'));
}
};
Forever.prototype.onError = function(errHandler) {
if ('function' === typeof errHandler) {
this.on('error', errHandler);
} else {
this.emit('error', new Error('You should use a function to handle the error'));
}
return this;
};
示例用法:
var Forever = require('path/to/this/file');
var f = new Forever();
// function to be runned
function say(content1, content2){
console.log(content1 + content2);
}
//add function to the loop
//the first argument is the function, the rest are its arguments
//chainable api
f.add(say, 'hello', ' world!').run();
//stop it after 5s
setTimeout(function(){
f.stop();
}, 5000);
就是这样。
您可以创建一个子进程(fork)来检查您的实际进程是否响应。如果没有响应,Fork将向父级发送消息-杀死父级和Fork。你可以在要点中看到类似的内容:https://gist.github.com/kevinohara80/3173692
如果您将使用expressnode.js服务器,您可以尝试中间件harakiri,它可以满足您的需要。
我想介绍我的解决方案。在我的例子中,我有几个无限循环(while(true)
),它们只由break
语句终止。很难确定是否达到了这些break
语句的条件,而且该算法不是我自己开发的,因此完全重构也不是一种选择。
我喜欢@JasonSebring使用循环计数器的简单解决方案。在我的情况下,仅仅设置迭代次数的限制就可以了。但我不想把所有这些变量都插入到我的代码中,而且我需要一个可以使用嵌套循环的解决方案。所以我想出了这个包装函数:
/**
* Stop potential infinite loops after a certain number of iterations.
* @param loopLimit - The maximum number of iterations before loop is aborted.
* @param silentStop - Whether to abort the loop silently or throw an error instead.
* @param callBack - Function representing the inner code of the loop.
*/
static finiteLoopHelper(loopLimit, silentStop, callBack) {
let loopCounter = 0;
let stopLoop = false;
while (!stopLoop) {
// Return value from the callback can invoke an early stop, like a break statement.
stopLoop = callBack();
loopCounter++;
if (loopCounter >= loopLimit) {
stopLoop = true;
if (!silentStop) {
throw Error(`Loop aborted after ${loopLimit} iterations.`);
}
}
}
}
用法如下:
let someVariable = 0;
finiteLoopHelper(1000, false, () => { // this line replaces "while (true) {"
someVariable = someCalculation();
if (someVariable === someCondition) {
return false; // like continue in a normal loop.
}
codeNotExecutedInCaseOfContinue();
if (someVariable === someOtherCondition) {
return true; // like break in a normal loop.
}
// Return value at the end can be omitted, because without it the function
// will return undefined which also keeps the loop running.
// return false;
});
如果您的循环以前有一个条件,则必须在箭头函数中检查此条件,并像上面的示例中那样使用return true;
。
由于循环计数器没有公开,因此可以嵌套此解决方案,而无需为内部循环的计数器查找不同的变量名。
在函数中,只需返回false或undefined。
在函数中手动抛出新错误("Error")。
将函数设置为在计时器上运行–var timer=setInterval(function,1000)。然后清除它以停止-clearInterval(计时器)
使用可以终止的工作线程运行脚本。
使用window.stop()阻止页面加载和运行。
仅适用于NodeJS–使用process.abort()或process.exit().
- 为什么我使用javascript获得了一个无限的for循环
- javascript停止一个无限循环
- setTimeout 会创建一个无限循环
- 为什么我有一个无限循环
- 为什么(;;){…}是一个无限循环
- 为什么“;window=window.parent"创建一个无限循环
- 把我的折线放在一个无限循环中
- 为什么这个树的布局给了我一个无限的循环
- JavaScript:为什么这会导致一个无限循环
- 两个同步事件创建了一个无限循环
- 为什么我的javascript代码会进入一个无限循环
- 为什么这会导致一个无限循环
- 在一个无限循环风格的展示中预先加载相邻的条目
- addEventListener创建了一个无限循环
- 在Jquery中创建一个无限循环
- 为什么这段代码创建了一个无限循环?
- Select2 trigger("change")创建一个无限循环
- 为什么这会产生一个无限循环
- 是否有任何解决方案来结束一个无限循环函数
- 为什么我的角脚本运行一个无限循环