JavaScript停止无限循环

这是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() 

所以基于我想要做的几个问题。

  1. 如果infiniteloopvariables设置为true,循环将停止?
  2. 我如何检测无限循环? 每3秒检查一次会很好。
  3. 如果infiniteloopvariables处于同一个进程中,则该variables在循环中不能更改。 我必须将variables存储在不同的进程中?
  4. 无论检测到无限循环需要生活在一个不同的过程? 理想情况下,同样的过程将是很好,但无论工程?

谢谢你的帮助。

基于其他提议混合的解决scheme:

 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。

无穷在这种情况下取​​决于循环的最大迭代是什么。 这段代码阻止了JavaScript的单线程本质,所以无论如何,除非您使用web worker,否则您将locking所有内容。 最好不要每隔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(); 

这段代码会不停地打招呼 ,直到你停下来。

 //stop the loop: clearImmediate(immediateId); 

为什么使用setImmediate

  1. 记忆力低下,不会造成记忆韭菜;
  2. 不会抛出RangeError: Maximum call stack size exceeded ;
  3. performance很好;

此外,

我创build了这个模块来轻松pipe理无限循环:

 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); 

而已。