【问题标题】:What is the alternative to Node.js domain module? [closed]Node.js 域模块的替代方案是什么? [关闭]
【发布时间】:2016-03-03 09:29:49
【问题描述】:

domain built-in module 将被弃用:

稳定性: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");

【问题讨论】:

  • 全局错误处理程序在 node.js 中除了关闭你的服务器之外真的没有任何作用,因为他们无法确切知道问题的上下文以及如何恢复。如今,更好的方案是对所有异步代码使用 Promise,然后至少在您可以实际处理错误的 Promise 的顶层捕获错误。 Promise 会自动为您捕获异常并将它们转换为 Promise 错误处理程序。
  • @jfriend00 就我而言,我无法控制它,因为这是用户提供的功能,我真的不想在发生错误时中断进程。也许vm 模块可能是一个解决方案?
  • 用户提供的代码可能会对您的服务器造成可怕的影响,除非您在单独的沙盒进程中运行它,否则您无法保护自己免受它的侵害。 vm 模块可能会被证明是有用的,但即使那样你也必须小心。
  • @jfriend00 在我的情况下,开发人员将代码作为函数提供,我正在编写的库应该处理函数中的任何错误。
  • 您无法在开发人员提供的代码中捕获异步操作中的错误。他们只是不会冒泡到顶层。你可以尝试/捕捉任何你称之为他们的东西,这就是你所能做的。除此之外,开发人员提供的代码是否能够聪明地处理自己的错误。

标签: javascript node.js asynchronous try-catch


【解决方案1】:

由于您在这里遇到的真正问题显然是如何保护您的服务器免受用户提供的代码的影响,您需要将用户提供的代码从您的主进程中取出,并置于一个不会对您的服务器造成不良影响的沙盒环境中或服务器的文件系统。我建议您从 vm module 开始,但即便如此,也有很多关于如何保护您的系统的信息。

您可能还对vm2 module 感兴趣,它在vm 模块之上添加了一些额外的安全功能。

一些相关文章:

Safely sandbox and execute user submitted JavaScript?

How to run user-submitted scripts securely in a node.js sandbox?

A Nifty Javascript Sandbox for Node.js

Node.js Virtual Machine (vm) Usage

Using Docker to Sandbox Untrusted Node JS Code


如果您只是想捕捉开发人员提供给您的任何代码中的错误,那么您几乎所能做的就是将 try/catch 放在您从外部世界调用的任何内容上。

如果第 3 方代码在异步代码中有错误,这些错误将不会冒泡到任何顶层,因此您无能为力。您也无法阻止此第 3 方代码泄漏资源(如文件句柄、内存等)。

基本上,如果您要在您的进程中运行第 3 方代码,您需要相信它是好的代码、编写良好、不会泄漏、处理自己的错误并且不会尝试进行恶意操作事物。如果你不能信任所有这些东西,那么它应该在一个沙盒中用完进程,在那里你至少有更多的保护。

【讨论】:

  • 这里并不是真正的服务器案例,但很高兴知道这一点。就我而言,我正在为 Node.js 编写一个单元测试库。可以举个例子吗?
  • @IonicăBizău - 有很多文章用示例和教程编写。请参阅我添加到答案中的链接。而且,如果您需要更好的帮助,您可以编辑您的问题以更详细地定义您实际尝试解决的问题。现在,您的问题询问的是您尝试过的一种解决方案,实际上并未描述您尝试解决的整体问题。
  • 当然,我改进了我的问题。我正在检查链接。我已经用谷歌搜索了很多,但最后问了这个问题。 :D
  • @IonicăBizău - 我在答案末尾添加了更多内容。
  • 如果第 3 方代码在异步代码中有错误,这些错误将不会冒泡到任何顶层,因此您无能为力。domain模块可以做到这一点,我今天想找到这样做的好方法,因为我想向用户显示友好的错误。
【解决方案2】:

据我所知,domain 没有替代品。还有两个主要的努力来取代它的功能:

  • AsyncWrap,跟踪上下文,但不直接暴露给用户空间
  • 通过v8 和Chrome 开发工具提高可调试性,请参阅here

除了使用 vm 听起来适合你的情况。

【讨论】:

  • 除了使用 vm 听起来适合你的情况。 –– 在上下文中运行代码时有没有办法捕获错误(例如 runCode("foo").on("error") 之类的东西)?谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-20
  • 2021-07-25
  • 1970-01-01
  • 2021-11-13
  • 2018-12-01
相关资源
最近更新 更多