5

我的 Node.js 应用程序提供了 WebSockets 和 RESTful接口。我写了一个小替代品Backbone.synch来使用 Socket.IO 作为传输。

DRY 问题:在客户端事件上执行的回调包含与 RESTul 路径的回调几乎相同的逻辑。客户端发出的事件和数据之间的示例映射,以及相应的操作:

+----------------+---------------------------------+--------------------+
| event emitted  | data emitted                    | RESTful URL        |
+----------------+---------------------------------+--------------------+
|     read:users | empty string                    |  GET /users        |
|     read:users | id of the model                 |  GET /users/:id    |
|   create:users | full model as JSON              |  POST /users       |
|  destroy:users | id of the model                 |  DELETE /users/:id |
|   update:users | full model as JSON (with id)    |  PUT /users/:id    |
|    patch:users | partial model as JSON (with id) |  PUT /users/:id    |
+----------------+---------------------------------+--------------------+

示例(99% 的重复逻辑/代码):

var UserModel = require('./models/user'); // Mongoose model

// Express path
app.get('/users/:id?', function (req, res)) {
    var query = !id ? {} : { _id: id };

    UserModel.find(query, function (err, doc) {
        return err ? res.send(404, null) : res.send(200, doc);
    });
};

// SocketIO listening to the read:users event
socket.on('read:users', function(id, cb) {
    var query = !id ? {} : { _id: id }

    UserModel.find(query, function (err, doc) {
        return err ? cb(err.message, null) : cb(null, doc);
    });
});

因为我玩了几天 Node.JS 和事件编程(和 JavaScript),所以我正在寻找一个关于如何设计“控制器”的好建议,比如可以轻松处理重复代码的通用对象。谢谢。

4

1 回答 1

1

如果你真的想混合这两个函数的逻辑,那么你的客户端代码将参数传递给你的socket.on回调函数的方式将不得不改变。您可以像这样使用当前设置来处理它:

var veryGenericCallback = function(p1, p2) {
   // Note: Not sure what to name the arguments because they are wildly different
   // in your two different cases.

   var query = typeof p1 === "object" : {} : { _id: p1 };

   UserModel.find(query, function (err, doc) {
     var result;

     if (typeof p2 === "function") {
        return err ? p2(err.message, null) : p2(null, doc);
     } else {
        return err ? p2.send(404, null) : p2.send(200, dox);
     }

   });

}

但是正如您所看到的,在某些时候您仍然需要重复您试图避免的逻辑。但是,如果您socket发出事件的客户端代码传入一个对象,该对象在第一个参数上具有“id”属性,并为您的第二个参数传递了一个带有send函数的对象,您可以将其简化为:

var veryGenericCallback = function(info, action) {

   var query = info.id ? { _id: info.id } : {};

   UserModel.find(query, function (err, doc) {

     return err ? action.send(404, null) : action.send(200, doc);

   });

}

但是,在这种情况下,您需要更改服务器端的代码以处理您的伪发送方法所做的任何事情(并且您需要首先在客户端可以访问它的地方定义它)。这也严重限制了您可以在回调中执行的操作,因为您想要在实际请求/响应对象上调用的任何函数都必须在套接字客户端代码中进行模仿。在我看来,这会混淆代码的可读性和可扩展性,但它肯定是可以实现的。

于 2013-02-19T16:32:48.473 回答