每次我使用新的菜单项更新数据库时,我都试图通过另一条路线来更新路线。这是我很难过的丑陋尝试:
在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,它甚至会显示一条很酷的新路由。但是,刷新页面并单击新路线应在其中运行的链接后,出现未定义的错误。
管理员将数据传递给我的Page控制器:
// 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中的动态加载程序,一切都会再次正常运行。但是,在数据库更新后,是否没有办法重新加载路由?我的技术在这里不起作用,并且像我在这里所做的那样,将主应用程序传递给控制器是很丑陋的。
我建议两个更改:
使用setTimeout进行异步的概念菜单db函数的证明,您将用实际的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 db调用)。
编辑:哦,我刚才看到了您的Model.js。那里的问题是this
指您返回的对象:
{
setDB: function(db) {
this.db = db;
},
getlist: function(callback, query) {
this.db.find(query || {}, function (err, doc) { callback(doc) });
}
}
因此,默认情况下没有数据库。并且由于您app
在初始页面加载中将内容附加到,因此您确实得到了一些东西。
但是,在当前的更新功能中,您将东西附加到了新应用程序(reqApp = req.app
)上,因此现在您不是在与原始应用程序对话,而是与它的另一个实例对话。而且我认为您的后续请求(更新后)将范围混为一谈,因此与实际最新数据失去联系。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句