如何设置函数执行的限制时间

时间:2018-12-26 22:17:36

标签: javascript

我想为要执行的功能设置一个限制时间,如果它当时无法完成其工作,则应该中止该功能的执行。我必须用什么方式处理它。我以为我会在运行时为每个函数创建一个“ setTimeout”,但我想不出一种方法来中止函数的执行,除非它位于“ setTimeout”中,而我可以给它“ cleanTimeout”并中止,但是可以想到其他方法吗?

  

示例

超时:

const eventBus = new EventEmitter();

function Timeout(parent) {
    this.id = undefined;
    this.parent = parent;
}

Timeout.prototype.set = function(limitTimeMs) {
    const parent = this.parent;

    this.id = setTimeout(function() {
        eventBus.emit('runEnd', parent);
    }, limitTimeMs);
}

Timeout.prototype.clear = function() {
    clearTimeout(this.id);
}

亚军:

function Runner() {
  this.tests = [];
  eventBus.on('runEnd', function(test) {
    console.log('runEnd');
    // results ready for the preview layer...
  });
  eventBus.on('testEnd', function(test) {
    console.log('testEnd');
  });
}
Runner.prototype.addTest = function(test) {
  this.tests.push(test);
}
Runner.prototype.run = function() {
    for(let i = 0; i < this.tests.length; i++)
      this.tests[i].run();
}

测试:

function Test(fn, limit) {
    this.fn = fn;
    this.limit = limit;
    this.timeout = new Timeout(this);
}
Test.prototype.run = function() {
    this.fn.call(this);
    this.timeout.clear();
    eventBus.emit('testEnd', this);
}

主要:

const runner = new Runner();
const test1 = new Test(function() {
    this.timeout.set(1);  
    let i = 0;
    while(i < 1000000000)
        i++;
});
runner.addTest(test1);
runner.run();
  

实际示例:

http://playcode.io/197465?tabs=console&script.js&output

我已经简化了最大值,我还必须处理异步的“测试”。问题是我最多可以配置“ this.timeout.set(0);”。仍然是“ fn();”首先执行,即使在上面的“ while”中花了很长时间,还是“ this.timeout.set(0);”在它之后运行。我知道要调用“ setTimeout”有一个最小值,即“ 4ms”(取决于浏览器),我必须能够处理什么替代方案?请注意,我无法修改“ fn”功能,只能在其之前或之后添加代码。

我意识到我试图做的事情对于单个线程来说是荒谬的,如果立即执行“ setTimout(0)”,那当然可以奏效,但是仍然存在测试函数将继续执行它的问题执行,这是处理问题的非常难看的方法。我发现了另一种方法,因为我想避免“ stackoverflow”错误,因此我根据Web Worker的 @blex 示例进行了此操作,它可以正常工作,但是后来我想,为什么我应该这样做?想避免“ stackoverflow”?那不是很糟糕吗?如何知道它是否会导致错误,这可能会令人困惑,但是我仍然继续,因为我需要知道我是否可以这样做,在这里就可以了:

http://playcode.io/198133?tabs=console&index.html&output

但是我想更好,我不想避免“堆栈超出”错误,如果发生,最好让我知道。因此,我将以其他方式处理,这比较简单,我将选择初始时间,然后是测试结束时的时间,将持续时间与超时进行比较,如果超过了超时时间,那么我会出错。我不再认为该问题是问题,该函数将执行到最后以检查时间是否已到,从而无法避免出现“堆栈超出”错误。

1 个答案:

答案 0 :(得分:0)

您可以使用生成器在两者之​​间产生执行,然后检查时间是否结束:

function runMax(fn, max) {
   const endAt = Date.now() + max;
   let done, iterator = fn();
   do {
     ({ done } = iterator.next());
     if(Date.now() >= endAt) return;
  } while(!done) 
}

console.log("start");
runMax(function* () {
  while(true) {
    // some long running code
    console.log("do stuff");
    // sometimes yield inbetween:
    yield;
  }
}, 1000);
console.log("aborted");