Node.js领域模块的替代方案是什么?

11

domain内置模块将会被弃用:

稳定性:0 - 已弃用

此模块正在等待弃用。 一旦替代API确定,此模块将被完全弃用。 大多数最终用户不应该使用此模块。 那些绝对需要域提供的功能的用户可以在现有时间内依赖它,但应该预期将来必须迁移到其他解决方案。

根据此信息,他们目前并没有真正推荐一个解决方案。但是如何实现与以下功能类似的功能:

var d = require('domain').create();
d.on('error', function(err) {
  console.log(err);
});
d.run(function() {
  setTimeout(function () {
     throw new Error("Something went really wrong in async code.");
  }, 1000);
});

所以,这个处理异步错误的方法很好用,但是domain模块已经被弃用了。

如何将这段代码迁移到更好的东西?


我的使用案例是,我正在编写一个库,它接受一个函数作为输入,并运行该函数并显示结果(实际上,您可以将其视为单元测试库):

myLib.it("should do something", function (done) {
   setTimeout(function () {
        // Some async code
        // ...
        // But here an error is thrown
        throw new Error("dummy");
   }, 1000);
});

显然,我不想在这种情况下中断进程,但我希望显示一个漂亮的错误(基本上是在此函数中捕获错误)。

目前在库中我这样做:

var err = null;
try {
   fn(callback);
} catch (e) {
   err = e;
}

console.log(err || "Everything went correctly");

1
全局错误处理程序在Node.js中除了关闭服务器外,实际上并不能知道出了什么问题以及如何恢复。现在更好的方案是对所有异步代码使用Promise,然后至少在Promise的顶层捕获错误,这样您就可以真正地处理错误。Promise会自动捕获异常并将其转换为Promise错误处理程序。 - jfriend00
@jfriend00 在我的情况下,我无法控制这个问题,因为这是由用户提供的函数,我真的不想在出现错误时中断进程。也许 vm 模块可以是一个解决方案? - Ionică Bizău
1
用户提供的代码可能会对您的服务器造成严重影响,除非您在单独的沙盒进程中运行它,否则无法保护自己免受其影响。 vm 模块可能会证明有用,但即使如此,您仍需要小心谨慎。 - jfriend00
在我的情况下,开发人员提供代码作为函数,我正在编写的库应该处理函数中的任何错误。 - Ionică Bizău
在开发人员提供的代码中,您无法捕获异步操作中的错误。它们只是不会冒泡到顶层。您可以在调用他们的任何内容周围放置try/catch,这就是您能做的全部。除此之外,处理自己的错误对于开发人员提供的代码来说是很重要的。 - jfriend00
2个回答

3
由于您的真正问题似乎是如何保护服务器免受用户提供代码的攻击,因此您需要将用户提供的代码从主进程中移出,并置于一个沙盒环境中,以防止其对服务器或服务器文件系统造成危害。我建议您从vm模块开始,但即使在那里,也有很多关于如何保护系统的内容需要阅读。
您还可能对vm2模块感兴趣,该模块在vm模块的基础上添加了一些其他安全功能。
一些相关文章:
- 如何安全地隔离和执行用户提交的JavaScript脚本? - 如何在Node.js沙盒中安全地运行用户提交的脚本? - 用于Node.js的漂亮的JavaScript沙盒 - Node.js虚拟机(vm)的使用 - 使用Docker隔离不受信任的Node JS代码
如果您只是想捕获由开发人员提供给您的任何代码中的错误,那么您可以在从外部世界调用的任何内容周围添加try/catch。
如果第三方代码存在异步代码错误,则这些错误将不会冒泡到任何顶层,因此您对此无能为力。您也无法防止这个第三方代码泄露资源(如文件句柄、内存等)。
基本上,如果您要在进程中运行第三方代码,您需要相信它是好代码,编写良好,不会泄漏,处理自己的错误并且不会尝试执行恶意操作。如果您不能信任所有这些内容,那么它应该在一个沙盒中以进程外运行,这样您至少还有更多的保护措施。

@IonicăBizău - 有很多带有示例和教程的文章。请查看我在答案中添加的链接。如果您想获得更好的帮助,您应该编辑您的问题,更详细地定义您实际要解决的问题。现在,您的问题只是询问您尝试过的一个解决方案,并没有实际描述您正在尝试解决的整个问题。 - jfriend00
如果第三方代码在异步代码中存在错误,这些错误将不会冒泡到任何顶层,因此您无法对其进行任何处理。但是,domain模块可以做到这一点,我今天想找到一个好的方法来实现它,因为我想向用户显示友好的错误信息。 - Ionică Bizău
@IonicăBizău - 我认为你所要求的东西不存在,原因是你无法通过在顶层处理来安全地从深层错误中恢复。以下是域模块文档中的一句话: 此模块正在等待废弃。一旦替换API已经确定,此模块将被完全废弃。大多数终端用户不应该使用此模块。绝对必须具备域提供的功能的用户可以在目前依赖它,但应该预计将来需要迁移到其他解决方案。 - jfriend00
它目前存在于domain模块中,但由于该模块将被弃用,我该如何解决?通过查看代码,domain相关内容以一些C++代码结束。 - Ionică Bizău
谢谢澄清,我明白了! :-) 平安! - Ionică Bizău
显示剩余6条评论

1
据我所知,没有可以直接替换 domain 的解决方案。此外,有两个主要的努力来替代它的功能:
  • AsyncWrap,它可以跟踪上下文,但不直接暴露给用户
  • 通过 v8 和 Chrome Dev Tools 增加调试能力,请参见这里
除此之外,对于您的情况,使用 vm 似乎是合适的。

除此之外,使用虚拟机似乎很适合你的情况。有没有一种方法可以在运行代码时捕获错误(例如,像 runCode("foo").on("error") 这样)?谢谢! - Ionică Bizău

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接