I'm using 'express-namespace' to categorize my routing. Here is my code.
..
9 var controllers = require('./controllers');
10 require('express-namespace');
..
46
47 app.namespace('/json', function(){
48 app.post('/', function(req, res, next){
49 res.header('Content-Type', 'application/json');
开发者_StackOverflow社区50 next();
51 });
52 /**
53 * Map the controller objects and its actions
54 * to the corresponding URL in lower case
55 */
56 for(var controller in controllers){
57 app.namespace('/' + controller.toLowerCase(), function(){
58 controller = controllers[controller];
59 for(var action in controller){
60 app.post('/' + action.toLowerCase(), function(req,res){
61 action = controller[action];
62 action(req, function(result){
63 res.send(result);
64 });
65 });
66 }
67 });
68 }
69 });
and here is my ./controllers.js code:
...
4 var Users = {
5 };
6
7 Users.create = function(req, result){
...
22 }
23
24 exports.Users = Users;
25
My point is to move my controllers code into a single .js file and map all my controllers into corresponding lower-case URL so my app is pretty neat.
This works out pretty good for the first POST every time I run 'node app.js'. If I POST to the URL for the second time, the following exception occurs:
TypeError: undefined is not a function
at CALL_NON_FUNCTION (native)
at /home/carl/source/node/funner/app.js:62:21
at callbacks (/usr/local/lib/node/.npm/express/2.4.6/package/lib/router/index.js:272:11)
at param (/usr/local/lib/node/.npm/express/2.4.6/package/lib/router/index.js:246:11)
at pass (/usr/local/lib/node/.npm/express/2.4.6/package/lib/router/index.js:253:5)
at Router._dispatch (/usr/local/lib/node/.npm/express/2.4.6/package/lib/router/index.js:280:4)
at Object.handle (/usr/local/lib/node/.npm/express/2.4.6/package/lib/router/index.js:45:10)
at next (/usr/local/lib/node/.npm/connect/1.7.0/package/lib/http.js:201:15)
at /usr/local/lib/node/.npm/connect/1.7.0/package/lib/middleware/session.js:323:9
at /usr/local/lib/node/.npm/connect/1.7.0/package/lib/middleware/session.js:342:9
Can anyone give me a hint here?
I don't see a clear error, but I do see some dangerous javascript. for( key in obj ) statements should be filtered by hasOwnProperty ifs and it's important to use var statements to scope local variables in functions within loops.
47 app.namespace('/json', function(){
48 app.post('/', function(req, res, next){
49 res.header('Content-Type', 'application/json');
50 next();
51 });
52 /**
53 * Map the controller objects and its actions
54 * to the corresponding URL in lower case
55 */
56 for(var controller in controllers){
**if(controller.hasOwnProperty(controller) {**
57 app.namespace('/' + controller.toLowerCase(), function(){
58 **var mycontroller** = controllers[controller];
59 for(var action in mycontroller){
**if(mycontroller.hasOwnProperty(action) {**
60 app.post('/' + action.toLowerCase(), function(req,res){
61 **var myaction** = mycontroller[action];
62 myaction(req, function(result){
63 res.send(result);
64 });
65 });
}
66 }
67 });
}
68 }
69 });
I haven't used express-namespace
but I think you can just map the urls for the controllers as they come using req.params
. Like so:
app.namespace('/json', function(){
app.post('/:controller/:action', function(req, res, next){
var controller = req.params.controller,
action = req.params.action;
controller[0] = controller[0].toUpperCase();
if( controllers[ controller ][ action ] ){
res.header('Content-Type', 'application/json');
controllers[ controller ][ action ](req, function(result){
res.send(result);
});
}
else
res.send('Action %s is not defined for the %s controller', action, controller);
});
});
And the same can be done for app.post('/:controller', ...);
Tell me if it works.
PD. I'm new to node+express
.
精彩评论