1

在我的 node.js 应用程序中,我曾经按域处理错误。该应用程序的架构如下所示:

  1. 控制器。快速路由调用控制器方法

  2. 控制器调用服务和使用模型

  3. 服务调用存储库

(其实和DDD很像)。

因此,控制器创建域,并在域中运行其实际主体。如果出现问题,服务会抛出异常。控制器还监听域错误并处理它们。它非常舒服,因为我不需要担心在所有服务的方法调用堆栈上出现错误——我只是抛出一个异常并且可以确定它会在控制器中被捕获。

但是我遇到了与使用 PostgreSQL 相关的问题。我使用 node-postgres 模块,并在单独的 js 文件中创建 pg.Client,因此 pg.Client 就像为所有人共享(否则,在每个查询上创建 pg.Client 会打开许多​​与 postgres 的活动连接)。

问题在于,当 pg.Client 在单独的文件中定义时,它就像一个全局对象,并且不包含在控制器中创建的域范围内。因此从 pg.Client 回调抛出的异常不会被域捕获。

我将展示简化的请求处理方式以使其清楚。假设用户想通过 userId 登录:

  1. 在开始的 pg.Client 创建的某个地方

  2. 获取请求来快递,快递调用路由方式

  3. 路由调用一些控制器的方法

  4. 控制器创建域并在 «domain.run» 中调用服务

  5. 服务调用存储库

  6. Repository 获取之前创建的 pg.Client,并调用 sql 查询方法

  7. sql查询方法的结果放入回调中(所以这个回调被pg.Client调用)

  8. 然后回调在服务中处理,我们检查我们得到 null 而不是用户模型(因为给定 userId 在 db 中没有这样的用户)并抛出异常

因此该异常不会在域中捕获。从技术上讲,我们需要使用节点域的 «add» 方法并添加 pg.Client,但我所说的 pg.Client 是共享的,因此它将添加到不同的并发域中。

我将列出一些代码示例以使其更清楚。它是 UserService 的简化方法:

 login: function (email) {

                    var userRepository = new UserRepository();
                    userRepository.findByEmail(email, function (model) {
                        if (model == null)
                           throw new Error('No such user');
                    });

            }

因此,该方法«login»在域中被调用。但它创建了 userRepository,调用 findByEmail 方法,该方法将使用位于域范围之外的共享 pg.Client,这就是为什么域中不会捕获异常的原因。

任何想法如何修复它并将 pg.Client 放入域中?

4

1 回答 1

0

我解决了这个问题。我在活动域范围内创建 EventEmitter 并听让我们说“onCallback”事件。在查询方法的回调中(不与域连接,因为 pg.Client 有点全局并且位于域之外)我发出 EventEmitter 的 «onCallback»。

于 2013-08-03T16:58:32.767 回答