Express.js的动态路由-甚至可能吗?

布兰登·明顿

每次我使用新的菜单项更新数据库时,我都试图通过另一条路线来更新路线。这是我很难过的丑陋尝试:

在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中的动态加载程序,一切都会再次正常运行。但是,在数据库更新后,是否没有办法重新加载路由?我的技术在这里不起作用,并且像我在这里所做的那样,将主应用程序传递给控制器​​是很丑陋的。

蜜糖

我建议两个更改:

  1. 将此菜单附件移至单独的模块。
  2. 在使用它时,请进行一些缓存。

使用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] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Express.js动态路由

来自分类Dev

Express.js中的路由-参数的动态数量

来自分类Dev

Express JS中用于动态路由的对象数组

来自分类Dev

如何使用express.js配置动态路由

来自分类Dev

Express.js中的路由-参数的动态数量

来自分类Dev

Express JS中用于动态路由的对象数组

来自分类Dev

使用 Express JS 的路由

来自分类Dev

甚至可以使用 Express Checkout 进行定期付款吗?

来自分类Dev

未找到 Node.js、JQuery 和 Express.js 路由,仅返回 404。其他人可以帮助指出可能出了什么问题吗?

来自分类Dev

在Express.js中路由

来自分类Dev

Express.js路由组织

来自分类Dev

基于数据库条目的动态express.js路由,无需重启

来自分类Dev

可以在收听时添加到Node.js Express的路由吗?

来自分类Dev

可以在收听时添加到Node.js Express的路由吗?

来自分类Dev

Express.js 可以将 localhost:3000 和 localhost:3000/ 设置为不同的路由吗?

来自分类Dev

用于要打印的动态对象的类动态 Express 路由

来自分类Dev

Express.js中的默认路由

来自分类Dev

如何保护express.js中的路由?

来自分类Dev

Express JS检索路由回调函数

来自分类Dev

Express JS路由中的过滤器

来自分类Dev

在Express JS中从路由调用函数对象

来自分类Dev

node.JS Express护照路由

来自分类Dev

使用express.js路由的Javascript函数

来自分类Dev

单元测试express.js路由

来自分类Dev

express.js通配符路由问题

来自分类Dev

节点js express中的冲突路由

来自分类Dev

在Express.js中合并路由

来自分类Dev

凉亭组件的Express.js路由

来自分类Dev

如何处理Express.js路由?