5

私のNode.jsアプリケーションは、WebSocketとRESTfulインターフェースの両方を提供します。Backbone.synchSocket.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

これら 2 つの関数のロジックを本当に混在させたい場合は、クライアント側のコードが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」プロパティを持つオブジェクトを渡し、send2 番目の引数に関数を持つオブジェクトを渡した場合、次のように減らすことができます。

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 オブジェクトで呼び出したい関数はすべて、ソケット クライアント コードで模倣する必要があるため、コールバックで実行できることも大幅に制限されます。私の意見では、これはコードの可読性と拡張性を混乱させますが、確実に達成できます。

于 2013-02-19T16:32:48.473 に答える