在节点js中设置超时故障

use*_*112 9 javascript exception-handling settimeout node.js

我有一个域异常处理程序(用于夜间测试的包装器).

我的异常处理程序包装器

var domainError = function(func) {

    return function() {
      var d = domain.create().on('error', function(err) {
        console.error(err.stack);
      });

      d.enter();
      try {
        return func.apply(this, arguments);
      }
      catch (err) {
        //do something with the err
      }
      d.exit();
    }
};
Run Code Online (Sandbox Code Playgroud)

我试图设置超时,这样return func.apply(this, arguments);就不会永远.

任何人都可以建议我如何添加超时并使域结束该功能并退出,如果超过超时?

Ben*_*aum 7

这在Node的并发模型中是不可能的.没有"中断" - 多处理是协同完成的.如果你从另一方面看它 - 你会得到一个非常有力的保证,你的代码几乎总是会运行完成.

您可以生成另一个子进程,然后抢占它(因为进程支持抢占).


终止同步函数的最简单方法是在它自己的"隔离"中执行它 - 这意味着它可以被杀死.请注意,这不像使专用工作者"进程"和使用async io与它进行通信那样高效 - 这可能更快 - 但这更容易.

var vm = require('vm'); // get the VM module

// when you want to run a bit 
function withError(func, context, timeout){
     var ctx = vm.createContext(context);
     var code = func.toString().slice(12).slice(0,-2)
     return vm.runInContext(code, ctx, {
        timeout: timeout,
        displayErrors: true; // to log, like in your version
     });
}
Run Code Online (Sandbox Code Playgroud)

请注意,此代码表示该函数无法访问闭包范围或参数,因此所有内容都必须在其范围内 - 它不像您想象的那么大,因为您可以转换:

function doFoo(x, y){
    return x + y + z; // z is from closure
}
Run Code Online (Sandbox Code Playgroud)

function doFoo(){
    return this.x + this.y + this.z;
}
Run Code Online (Sandbox Code Playgroud)

并称之为

withError(doFoo, {x:x, y:y, z:z }, 2000); // 2000 ms timeout
Run Code Online (Sandbox Code Playgroud)

通过使用生成语法树的词法分析工具,这也可以更好地自动化.

如果我可以建议一个替代方案 - func以一种可以控制它的方式编写您的方法 - 在这些情况下,协作式多任务处理更容易,并且更不容易出错.