【问题标题】:Using routes in Express-js在 Express-js 中使用路由
【发布时间】:2012-02-10 11:40:00
【问题描述】:

所以我开始使用 Node.js。我在Nodejs.org 上看到了 Ryan Dahl 的视频,听说他向网站推荐了 Express-js。

我下载了 Express 的最新版本,并开始编写代码。我在 / 上有一个完全成熟的静态视图,但是一旦我尝试发送参数,就会收到如下错误:

Cannot GET /wiki

我尝试按照expressjs.com 上的指南进行操作,但在最新版本中使用路线的方式发生了变化,导致该指南无法使用。

指南:

app.get('/users/:id?', function(req, res, next){
    var id = req.params.id;
    if (id) {
        // do something
    } else {
        next();
    }
});

由 Express 生成:

app.get('/', routes.index);

当我尝试添加另一条路线时,我的问题出现了。

app.get('/wiki', routes.wiki_show);

我尝试了很多方法,但我不断收到Cannot GET /wiki (404) 错误。

routes/index.js 看起来像这样:

exports.index = function(req, res) {
    res.render('index', { title: 'Test', articles: articles, current_article: current_article, sections: sections })
};

我在那里做的唯一一件事就是添加一些参数(同一个文件中的数组),这就是我的工作。但是当我复制内容并将exports.index 更改为exports.wiki 或exports.wiki_show 时,我仍然收到Cannot GET /wiki 错误。

谁能向我解释我在这里缺少什么? - 谢谢。

【问题讨论】:

  • 你添加路由器中间件了吗?
  • 你下载了最新的快递?你是从 github 还是通过 NPM 获得的?
  • @DeaDEnD 是的,我很确定 :)
  • @RyanOlds 我是从 GitHub 得到的 :)
  • Master 不稳定。使用 NPM 安装它,你应该得到 2.5.6。另外,指定路由时会自动绑定路由中间件。

标签: node.js url-routing express


【解决方案1】:

没有人应该一直写 app.use('/someRoute', require('someFile')) 直到它形成一堆代码。

花时间调用/定义路由完全没有意义。即使您确实需要自定义控制,也可能只是在某些情况下,并且在大多数情况下,您希望能够创建一个标准的路由文件结构并让一个模块自动完成。

试试Route Magic

随着您扩展应用程序,路由调用将开始形成大量无用的代码。您只想使用 Route Magic 执行 2 行代码来处理所有 app.use 路由调用,如下所示:

const magic = require('express-routemagic')
magic.use(app, __dirname, '[your route directory]')

对于那些你想手动处理的,只是不要使用将目录传递给 Magic。

【讨论】:

    【解决方案2】:

    route-map express 示例将 url 路径与对象匹配,而对象又将 http 动词与函数匹配。这将路由布置在树中,简洁易读。应用程序的实体也被编写为对象,其函数作为封闭的方法。

    var express = require('../../lib/express')
      , verbose = process.env.NODE_ENV != 'test'
      , app = module.exports = express();
    
    app.map = function(a, route){
      route = route || '';
      for (var key in a) {
        switch (typeof a[key]) {
          // { '/path': { ... }}
          case 'object':
            app.map(a[key], route + key);
            break;
          // get: function(){ ... }
          case 'function':
            if (verbose) console.log('%s %s', key, route);
            app[key](route, a[key]);
            break;
        }
      }
    };
    
    var users = {
      list: function(req, res){
        res.send('user list');
      },
    
      get: function(req, res){
        res.send('user ' + req.params.uid);
      },
    
      del: function(req, res){
        res.send('delete users');
      }
    };
    
    var pets = {
      list: function(req, res){
        res.send('user ' + req.params.uid + '\'s pets');
      },
    
      del: function(req, res){
        res.send('delete ' + req.params.uid + '\'s pet ' + req.params.pid);
      }
    };
    
    app.map({
      '/users': {
        get: users.list,
        del: users.del,
        '/:uid': {
          get: users.get,
          '/pets': {
            get: pets.list,
            '/:pid': {
              del: pets.del
            }
          }
        }
      }
    });
    
    app.listen(3000);
    

    【讨论】:

      【解决方案3】:

      您也可以将它们组织成模块。所以它会是这样的。

      ./
      controllers
          index.js
          indexController.js
      app.js
      

      然后在控制器的 indexController.js 中导出你的控制器。

      //indexController.js
      module.exports = function(){
      //do some set up
      
      var self = {
           indexAction : function (req,res){
             //do your thing
      }
      return self;
      };
      

      然后在控制器目录的 index.js 中

      exports.indexController = require("./indexController");
      

      最后在 app.js 中

      var controllers = require("./controllers");
      
      app.get("/",controllers.indexController().indexAction);
      

      我认为这种方法可以实现更清晰的分离,您也可以通过传入数据库连接来配置控制器。

      【讨论】:

        【解决方案4】:

        似乎只有 index.js 会在您 require("./routes") 时被加载。 我在 index.js 中使用了以下代码来加载其余的路由:

        var fs = require('fs')
          , path = require('path');
        
        fs.readdirSync(__dirname).forEach(function(file){
          var route_fname = __dirname + '/' + file;
          var route_name = path.basename(route_fname, '.js');
          if(route_name !== 'index' && route_name[0] !== "."){ 
            exports[route_name] = require(route_fname)[route_name];
          }
        });
        

        【讨论】:

        • 如果您不按某种命名空间对路由进行分组,这是避免使用大量 require 语句的好方法。
        • 实际上,将 ~last 行更改为 exports[route_name] = require(route_fname) 可以让您以后可以通过命名空间引用路由,例如routes.users.show.
        【解决方案5】:

        所以,在我创建了我的问题之后,我在右侧得到了这个相关列表,其中有一个类似的问题:Organize routes in Node.js。

        该帖子中的答案与Express repo on GitHub 相关联,并建议查看“route-separation”示例。

        这帮助我更改了我的代码,现在我可以使用它了。 - 感谢您的 cmets。

        我的实现最终看起来像这样;

        我需要在 app.js 中使用我的路线:

        var express = require('express')
          , site = require('./site')
          , wiki = require('./wiki');
        

        然后我像这样添加我的路线:

        app.get('/', site.index);
        app.get('/wiki/:id', wiki.show);
        app.get('/wiki/:id/edit', wiki.edit);
        

        我的应用根目录中有两个名为 wiki.js 和 site.js 的文件,其中包含:

        exports.edit = function(req, res) {
        
            var wiki_entry = req.params.id;
        
            res.render('wiki/edit', {
                title: 'Editing Wiki',
                wiki: wiki_entry
            })
        }
        

        【讨论】:

        • 快递很棒。作为初学者,从头开始构建 Web 服务器一次以了解 node.js 也很有用。我在这里找到了一个教程,我经历了然后直接表达:nodebeginner.org
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多