My 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,doc) { return err ? cb(err.message,null) : cb(null,doc); }); });
因为我正在使用Node.JS和事件编程(和JavaScript)几天,所以我正在寻找一个关于如何设计“控制器”的好建议,就像一个可以轻松处理重复代码的通用对象.谢谢.
解决方法
如果你真的想混合这两个函数的逻辑,那么你的客户端代码将参数传递给你的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,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); } }); }
但正如您所看到的,在某些时候您仍然需要重复您试图避免的逻辑.但是,如果发出事件的套接字客户端代码在第一个参数上具有“id”属性的对象中传递,并且传递了具有第二个参数的send函数的对象,则可以将其减少为:
var veryGenericCallback = function(info,action) { var query = info.id ? { _id: info.id } : {}; usermodel.find(query,doc) { return err ? action.send(404,null) : action.send(200,doc); }); }
但是在这种情况下,您需要更改服务器端的代码以处理伪发送方法所做的任何操作(并且您需要首先在客户端可以访问它的位置定义它).这也严重限制了您在回调中可以执行的操作,因为您要在实际的Request / Response对象上调用的任何函数都必须在套接字客户端代码中进行模仿.在我看来,这会混淆代码的可读性和可扩展性,但它肯定可以实现.