2013-02-19 55 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