2013-02-19 60 views
5

我的Node.js应用程序提供了这两个WebSockets和RESTful接口。我写了一个替换为Backbone.synch与Socket.IO一起用作传输。WebSockets加RESTful接口,如何在Node.js中编写DRY代码?

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); 
    }); 
}); 

因为我玩节点。 JS和事件编程(以及JavaScript)几天,我正在寻找一个很好的建议,说明如何设计一个“控制器”,就像一个能够轻松处理重复代码的通用对象。谢谢。

回答

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); 

    }); 

} 

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

+0

虽然我很欣赏你的努力,但我不得不说,我不同意你的回答。我知道哪些模块是,但您的解决方案只是将两个回调移动到一个单独的模块中。可以肯定的是,但我的问题是关于将它们组合的逻辑(与参数相关的问题)。不管怎么说,多谢拉! – Polmonino 2013-02-19 18:05:56

+0

我已经更新了我的答案,以证明在您当前的设置下,没有办法解决逻辑重复问题。但是,如果您调整了发出套接字事件的客户端代码,以便将具有与app.get()调用(请求和响应对象)中接收到的功能/属性类似的对象传递给对象,那么可以减少代码重复次数。然而,以我个人的观点来看,我认为这是不好的做法,因为你真的限制了你可以用这个函数做的事情(不需要在你的客户端套接字信息中增加更复杂的代码)。 – Default 2013-02-19 20:29:45