在app.js中,我检查菜单数据库和shazaam …路由是在启动时动态制作的.凉!:
// in app.js // var attachDB = function(req, res, next) { req.contentdb = db.content; req.menudb = db.menu; req.app = app; // this is the express() app itself req.page = PageController; next(); }; db.menu.find({}, function (err, menuitems){ for(var i=0; record = menuitems[i]; i++) { var menuitem = record.menuitem; app.all('/' + menuitem, attachDB, function(req, res, next) { console.log('req from app all route: ',req) PageController.run(menuitem, req, res, next); }); } http.createServer(app).listen(config.port, function() { console.log( '\nExpress server listening on port ' + config.port ); }); });
不是真正的优雅,但它是一个概念的证明.现在问题出现了:当我在Admin.js文件中保存一个新的菜单项时,数据库得到了更新,路由器似乎得到了更新,但点击带有动态创建路径的菜单链接后,请求就会爆炸
请求中的许多内容似乎都缺失了,我觉得有些基本的东西我不了解路由,回调或者这可能只是错误的解决方案.以下是负责创建新菜单项并在Admin.js文件中创建新路径的函数如下所示:
// in Admin.js // menuItem: function(req, res, callback) { var returnMenuForm = function() { res.render('admin-menuitem', {}, function(err, html) { callback(html); }); }; var reqMenudb = req.menudb, reqContentdb = req.contentdb, reqApp = req.app, reqPage = req.page; if(req.body && req.body.menuitemsubmitted && req.body.menuitemsubmitted === 'yes') { var data = { menuitem: req.body.menuitem }; menuModel.insert( data, function(err) { if (err) { console.log('Whoa there...',err.message); returnMenuForm(); } else { // data is inserted....great. PROBLEM...the routes have not been updated!!! Attempt that mimics what I do in app.js here... reqApp.all('/' + data.menuitem, function(req, res, next) { // the 2 db references below are set with the right values here req.contentdb = reqContentdb; req.menudb = reqMenudb; next(); }, function(req, res, next) { reqPage.run(data.menuitem, req, res, next); }); returnMenuForm(); } }); } else { returnMenuForm(); } },
保存管理部分中的数据工作正常.如果您控制日志app.routes,它甚至会显示一条非常酷的新路线.但是,刷新页面并单击新路径应该工作的链接后,我收到一个未定义的错误.
管理员将数据传递给我的页面控制器:
// in PageController.js // module.exports = BaseController.extend({ name: "Page", content: null, run: function(type, req, res, next) { model.setDB(req.contentdb); /* <-- problem here, req.contentdb is undefined which causes me problems when talking to the Page model */ var self = this; this.getContent(type, function() { var v = new View(res, 'inner'); self.navMenu(req, res, function(navMenuMarkup){ self.content.menunav = navMenuMarkup; v.render(self.content); }); }); }, getContent: function(type, callback) { var self = this; this.content = {} model.getlist(function(records) { if(records.length > 0) { self.content = records[0]; } callback(); }, { type: type }); }
最后,错误点在模型中
// in Model.js // module.exports = function() { return { setDB: function(db) { this.db = db; }, getlist: function(callback, query) { this.db.find(query || {}, function (err, doc) { callback(doc) }); },
最后,上面的getlist方法中的’this’是未定义的,导致页面爆炸.
如果我重新启动服务器,由于app.js中的动态加载程序,一切都会再次运行但是,在更新数据库后,是否有某种方法可以重新加载路由?我的技术不起作用,将主应用程序传递给控制器是很难看的,就像我在这里做的那样.
我建议两个改变:>将此菜单附件移动到单独的模块.
>当你在这里时,做一些缓存.
概念菜单db函数的证明,与setTimeout异步,你将用actuall db调用替换它.
// menuitems is cached here in this module. You can make an initial load from db instead. var menuitems = []; // getting them is simple, always just get the current array. We'll use that. var getMenuItems = function() { return menuitems; } // this executes when we have already inserted - calls the callback var addMenuItemHandler = function(newItem, callback) { // validate that it's not empty or that it does not match any of the existing ones menuitems.push(newItem); // remember, push item to local array only after it's added to db without errors callback(); } // this one accepts a request to add a new menuitem var addMenuItem = function(req, res) { var newItem = req.query.newitem; // it will do db insert, or setTimeout in my case setTimeout(function(newItem){ // we also close our request in a callback addMenuItemHandler(newItem, function(){ res.end('Added.'); }); }, 2000); }; module.exports = { addMenuItem: addMenuItem, getMenuItems: getMenuItems }
所以现在你有一个模块menuhandler.js.让我们构建它并在我们的应用程序中使用它.
var menuHandler = require('./menuhandler'); var app = express(); // config, insert middleware etc here // first, capture your static routes - the ones before the dynamic ones. app.get('/addmenuitem', menuHandler.addMenuItem); app.get('/someotherstaticroute', function(req, res) { var menu = menuHandler.getMenuItems(); res.render('someview', {menu: menu}); }); // now capture everything in your menus. app.get('/:routename', function(req, res){ // get current items and check if requested route is in there. var menuitems = menuHandler.getMenuItems(); if(menuitems.indexOf(req.params.routename) !== -1) { res.render('myview', {menu: menuitems}); } else { // if we missed the route, render some default page or whatever. } }); app.get('/', function(req, res) { // ... });
现在你没有去过db,如果没有新的更新(因为menuitems数组总是最新的),所以你的初始视图渲染速度更快(无论如何,对于那个1分贝的调用).
编辑:哦,我刚看到你的Model.js.问题在于,这是指您返回的对象:
{ setDB: function(db) { this.db = db; }, getlist: function(callback, query) { this.db.find(query || {}, function (err, doc) { callback(doc) }); } }
所以,默认情况下没有数据库.而且,由于您在初始页面加载中将某些内容附加到应用程序,因此您可以获得一些东西
但是在你当前的更新功能中,你将东西附加到新的应用程序(reqApp = req.app),所以现在你不是在谈论原始应用程序,而是另一个实例.而且我认为您的后续请求(更新后)使得范围全部混淆,因此失去了与实际最新数据的联系.