2012-07-13 3 views
4

이것은 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. infiniteloop 변수가 true로 설정되면 루프가 올바르게 중지됩니까?
  2. 무한 루프를 어떻게 감지합니까? 3 초마다 확인하는 것이 좋습니다.
  3. infiniteloop 변수는 동일한 프로세스에있는 경우 루핑 중에 변경할 수 없습니다. 변수를 다른 프로세스에 저장해야합니까?
  4. 무한 루프를 감지하는 것이 다른 프로세스에 있어야합니까? 이상적으로는 똑같은 프로세스가 좋지만 작동하는 것은 무엇입니까?

도움 주셔서 감사합니다.

+0

왜 반복 수에 상한값을 넣지 않으십니까? – jbabey

답변

2

해결책 :

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과 같은 다른 이벤트를 처리 할 수 ​​있습니다.

+0

이것은 내가 사용했던 것과 정확히 같지 않지만 여기에 대한 답은 나를 해결책으로 이끌었다. 감사. – Harry

+0

게시물을 편집하여 최종 솔루션을 추가 할 수 있습니까? –

1

이 경우 무한대는 루프의 최대 반복 횟수를 결정합니다. 이 코드는 JavaScript의 단일 스레드 특성을 차단하므로 웹 작업자를 사용하지 않는 한 모든 것을 잠글 수 있습니다. 이 코드는 간격이나 시간 초과가 실행되는 것을 막아주기 때문에 매 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++; 
    } 
} 
+0

루프가 무한합니다. 최대 반복을 설정할 수 없습니다. – Harry

+0

당신은 루프의 실행을 차단하는 방법을 가져야합니다. 예를 들어 setInterval을 사용하면 루프 내에서 작업을 생성 할 수 있습니다. 그렇지 않으면 차단 만 계속됩니다. 실제 예제를 작성해야합니다. 네트워크 통화 또는 이와 유사한 기능이 있으면 요청한 작업을 수행하는 데 완벽 할 것입니다. –

+0

예, 네트워크 통화에 대한 내용입니다. 이것은 서버 측 자바 스크립트이므로'infiniteloop' var을 반환 할 다른 프로세스를 호출 할 수 있다고 가정합니다. 그게 제가 질문 3에 대해 물었던 것입니다. – Harry

1

실제로 무한 루프를 중지 할 필요가 없습니다. 예를 들어 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. 성능이 좋습니다. 또한 더

,

나는 쉽게 무한 루프를 관리하기 위해이 모듈을 만든 :

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

합니다.