6

宿題:

ノードビギナーブック

Node.jsの使用を開始するにはどうすればよいですか[クローズ]

ノードでのハンドラーの構造化

裏話:私は自分のフレームワークを書いてみたかったのですが、おそらくそれを完全に理解していないために、いくつかの問題に直面しています。

私が達成したいのは、次のような構文です。

var app = require('./app'); //this part is understood and it works in my current code.
app.get('/someUrl', function(){ //do stuff here });
app.post('/someOtherUrl', function(){ //do stuff here });

私はこれと同じ構文を持つExpressフレームワークを知っていますが、それらのソースコードを読むことはまだ私を理解していません。

これを達成するのは簡単な作業かもしれませんが、私はまだそれを作成することはできません。

アプリケーションのより深いところにファイルを入れようとするとrequire('./app');、未定義のオブジェクトが生成されるため、サーバーはシングルトンオブジェクトであると推測しています。

だから私は何を試しましたか?

私の現在のコードはこのように見えます、そしてどういうわけか私はこれが進むべき道であるように感じます、しかし私はどうやらこのようにそれをすることができません。

require();読みやすくするために、すべてのステートメントを省略しています。

server.js:

var app = module.exports = {
    preProcess: function onRequest(request, response){
        processor.preRequest(request); //this object adds methods on the request object
        var path = urllib.parse(request.url).pathname;
        router.route(urls, path, request, response);
    },
    createServer: function() {
        console.log("Server start up done.");
        return this.server = http.createServer(this.preProcess);
    }
};

exports.app = app;

これを書いている時点では、このオブジェクトをget()メソッドで拡張することを試みています。

index.js:

var app = require('./server');
app.createServer().listen('1337');

ビットはrouter.route()基本的にリクエストをアプリケーションに送信し、router.jsファイル内で魔法をかけ、リクエストを(これまでのところ)/urlThatWasRequestedにマップする関数にルーティングします

これが私が残したい行動です。これはかなり難しい注文かもしれませんが、私のコードはすべて簡単に破棄でき、これは私自身のプロジェクトであるため、コードベース全体を書き直すことを恐れません。

私の質問を説明するのにこれで十分だと思います。これをもう少し明確にするために何を追加すべきかを言ってください。

前もって感謝します!

4

1 に答える 1

11

あなたの質問が何であるか正確にはわかりませんが、ここにいくつかの考えがあります:

1)ここで循環参照を作成しています:

var app = module.exports = {
    // some other code
}
exports.app = app;

appのプロパティとして追加しますapp。最後の行は必要ありません。

2)でハンドラーを保持する必要がありますapp。あなたはこのようなことを試すことができます:

var app = module.exports = {
    handlers : [],
    route : function(url, fn) {
        this.handlers.push({ url: url, fn: fn });
    },
    preProcess: function onRequest(request, response){
        processor.preRequest(request);
        var path = urllib.parse(request.url).pathname;
        var l = this.handlers.length, handler;
        for (var i = 0; i < l; i++) {
            handler = this.handlers[i];
            if (handler.url == path)
                return handler.fn(request, response);
        }
        throw new Error('404 - route does not exist!');
    },
    // some other code
}

この行を変更できることに注意してください。正規表現であるif (handler.url == path)ような方法で、それに対してテストします。もちろん、バリアントを実装することもできますが、私の経験から、リクエストがハンドラーにあるかどうかを確認する方が簡単です。これで、上記のコードを次のように使用できます。handler.urlpath.get.postGETPOST

app.route('/someUrl', function(req, res){ //do stuff here });

もう1つは、私が示したコードは、一致する特定のURLに対して最初のハンドラーのみを起動することです。多くのハンドラー(ミドルウェアなど)を含む、より複雑なルートを作成することをお勧めします。その場合、アーキテクチャは少し異なります。たとえば、次のようになります。

preProcess: function onRequest(request, response){
    var self = this;
    processor.preRequest(request);
    var path = urllib.parse(request.url).pathname;
    var l = self.handlers.length,
        index = 0,
        handler;
    var call_handler = function() {
        var matched_handler;
        while (index < l) {
            handler = self.handlers[index];
            if (handler.url == path) {
                matched_handler = handler;
                break;
            }
            index++;
        }
        if (matched_handler)
             matched_handler.fn(request, response, function() {
                 // Use process.nextTick to make it a bit more scalable.
                 process.nextTick(call_handler);
             });
        else
             throw new Error('404: no route matching URL!');
     };
     call_handler();
},

これで、ルート内で使用できます

app.route('/someUrl', function(req, res, next){ 
    //do stuff here
    next(); // <--- this will take you to the next handler
});

これにより、別のハンドラーに移動します(または、ハンドラーがなくなった場合は例外をスローします)。

3)これらの言葉について:

require('./ app'); アプリケーションのより深いファイルでは未定義のオブジェクトが生成されるため、サーバーはシングルトンオブジェクトであると推測しています。

それは真実ではありません。requireモジュールオブジェクトへの参照を常に返します。が表示されている場合はundefined、他の何かを台無しにしています(モジュール自体を変更しましたか?)。

最後の注意:少しお役に立てば幸いです。特にExpressのような優れたフレームワークがすでに存在するため、独自のフレームワークを作成するのは難しい作業になる可能性があります。でも頑張ってください!

編集

実装.get.setメソッドは実際には難しくありません。route次のように機能を変更する必要があります。

route : function(url, fn, type) {
    this.handlers.push({ url: url, fn: fn, type: type });
},
get : function(url, fn) {
    this.route(url, fn, 'GET');
},
post : function(url, fn) {
    this.route(url, fn, 'POST');
},

次に、ルーティングアルゴリズムで、typeプロパティが定義されているかどうかを確認します。そうでない場合は、そのルートを使用します(undefinedタイプは「常にルート」を意味します)。それ以外の場合は、リクエストのメソッドがタイプと一致するかどうかをさらに確認します。そして、あなたは完了です!

于 2012-07-11T08:57:22.620 に答える