【问题标题】:How to use Node.js 0.8.x domains with express?如何通过 express 使用 Node.js 0.8.x 域?
【发布时间】:2019-05-25 01:34:56
【问题描述】:

如何创建 Express/Connect 中间件,将每个请求包装在自己的域中?

【问题讨论】:

    标签: node.js express node.js-domains


    【解决方案1】:

    Speaker Deck 上的这组幻灯片提供了简洁的概述:

    从幻灯片中表达中间件代码:

    var createDomain = require('domain').create;
    
    app.use(function(req, res, next) {
      var domain = createDomain();
    
      domain.on('error', function(err) {
        // alternative: next(err)
        res.statusCode = 500;
        res.end(err.message + '\n');
    
        domain.dispose();
      });
    
      domain.enter();
      next();
    });
    

    【讨论】:

    • 你测试过这个吗?它对我不起作用,并且 domain.enter 在节点的站点上没有记录。
    • 这对我有用。我不知道为什么 domain.enter 没有记录。
    • 我应该补充一下,我担心这段代码调用 domain.enter 但没有相应的 domain.exit。似乎有可能泄漏。
    • 这确实有效。 enter 必须调用。是的,奇怪的是文档中没有。
    • 这条路线有问题。如果你没有错误。何时调用dispose?我在这里问了一个关于该主题的问题:stackoverflow.com/questions/14971028/…
    【解决方案2】:

    更新:下面描述的方法已在connect-domain NodeJS 模块中实现,可用于 Connect 或 Express 应用程序。

    从 Express 3 开始,express.createServer 已弃用,其回调应转换为中间件。在中间件中,将请求和结果对象添加到请求域非常重要,以便它们引发的错误由域错误处理程序处理。

    我的中间件看起来像这样:

    var domain = require('domain');
    
    app.use(function(req, res, next) {
        var requestDomain = domain.create();
        requestDomain.add(req);
        requestDomain.add(res);
        requestDomain.on('error', next);
        requestDomain.run(next);
    });
    

    如果您从顶级域中调用 http.createServer,则可以避免将请求和响应添加到请求域,但域文档似乎表明按请求域是最佳做法。

    请注意,上面的代码不会执行任何域清理操作,例如强制释放请求域。我的中间件选择再次通过中间件堆栈传递错误,以便稍后由特定的错误处理中间件处理。 YMMV。

    【讨论】:

    • 这不能防止在 3rd 方库中引发的异常... :(
    • @Jess,我承认这里的错误处理很幼稚,但我很好奇你看到了什么。理论上,任何异常都应该被域捕获,并作为“错误”参数提供给堆栈,假设您的处理程序有一个。
    • 我正在使用 sequelize,例如,如果 where 子句没有有效的语法,它将引发异常。我无法将代码更改为 emit 而不是 throw。我已经尝试了这里列出的所有解决方案,但似乎没有一个能捕捉到抛出的错误。
    • 您是否设置了错误处理中间件来接收错误,如此处所述? expressjs.com/guide.html#error-handling
    • @ChristopherCurrie 只是想我要补充一点,这种方法也适用于 Sails - 您将 connect-domain 添加到 sails.config.express.customMiddleware(仅限 http)或将其用作策略。
    【解决方案3】:

    我很幸运能更换库存

    var app = express.createServer();
    

    与:

    var domainCreate = require('domain').create;
    var app = express.createServer(function (req, res, next) {
        var domain = domainCreate();
        domain.run(next);
    });
    

    然后在您的中间件中,您可以向 process.domain 添加属性或添加额外的错误处理。

    【讨论】:

    • 这可能是一个很好的答案,但 express.createServer 已被弃用。
    • 如果您没有针对该域的特定错误处理,这样做的目的是什么?
    【解决方案4】:

    这是一个迟到的答案,但请查看express-domain-moddleware 模块。它会自动为每个请求创建一个新域。活动域可以由您的路由中的 process.domain 引用。这是一个例子:

    //with domain-middleware
    app.use(require('express-domain-middleware'));
    app.use(app.router);
    
    app.use(function errorHandler(err, req, res, next) {
      console.log('error on request %d %s %s: %j', process.domain.id, req.method, req.url, err);
      res.send(500, "Something bad happened. :(");
      if(err.domain) {
        //you should think about gracefully stopping & respawning your server
        //since an unhandled error might put your application into an unknown state
      }
    });
    
    app.get('/error', function(req, res, next) {
      db.query('SELECT happiness()', process.domain.intercept(function(rows) {
        fs.readFile('asldkfjasdf', process.domain.intercept(function(contents) {
          process.nextTick(process.domain.intercept(function() {
            throw new Error("The individual request will be passed to the express error handler, and your application will keep running.");
          }));
        }));
      }));
    });
    

    【讨论】:

    • 我对此表示赞同,因为express-domain-middleware 看起来是对这个问题最成熟(并且仍然保持不变)的答案。与同一作者的 node-ok 一起,看起来像是 node/express 中错误处理的强大解决方案。我将再添加一个与同一主题有些相关的链接:一旦发现错误如何响应:github.com/hapijs/boom
    【解决方案5】:

    这些域目前在节点中被弃用:

    https://nodejs.org/api/domain.html

    出于“分区错误”的目的,我创建了一个库,它允许您以一种很好的方式编写异步代码:https://github.com/vacuumlabs/yacol。它的好处之一是您可以拥有具有非常好的语义的类似域的行为;一探究竟!

    【讨论】:

      猜你喜欢
      • 2011-06-10
      • 1970-01-01
      • 2014-12-07
      • 2014-03-28
      • 1970-01-01
      • 1970-01-01
      • 2019-05-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多