express 的 app.get() 怎样理解?
发布于 12 年前 作者 jiyinyiyong 24298 次浏览 最后一次编辑是 8 年前

表示对所谓 Web 框架只停留在写一下 app.get() 那种水平… 帖子写一半想起去看源码… 怎么偏偏找不到 app.get = 的具体代码 https://github.com/visionmedia/express/blob/master/lib/application.js

首先在前边看到获取变量的解释:

Get setting name value

app.get('title');

而后面又是我更熟悉的处理 GET 请求的用法…

app.get('/', function(req, res){
  res.send('hello world');
});

这是为什么?

还有 app.params() app.use() app.engine() 我还好理解, 可前边的 app.set() 设置那么多变量那是做什么用的?

10 回复
/**
 * Delegate `.VERB(...)` calls to `.route(VERB, ...)`.
 */

methods.forEach(function(method){
  app[method] = function(path){
    if ('get' == method && 1 == arguments.length) return this.set(path); 
    var args = [method].concat([].slice.call(arguments));
    if (!this._usedRouter) this.use(this.router);
    return this._router.route.apply(this._router, args);
  }
});

若调用app.get()时只有一个参数,则认为是取设置值,否则认为是注册路由

@leizongmin 可恶的 arguments 变量… 不敏感 那再请问下 app.use() 的路由是怎样作用上去的, 我看 app.use() 被用了很多次, 而且 404 之类也通过它实现的… 疑问主要是 app.get()app.use() 之前是什么关系啊?

终于有点懂了, 所有被 app.use() 接收的 handle 会被放到一个 stack 里边 app.get() 执行的时候会把一条路由规则添加到 stack 里… 然后顺序检索 statck 直到结束, 那么执行这段代码给出 404 https://github.com/senchalabs/connect/blob/master/lib/proto.js#L122

    // all done
    if (!layer || res.headerSent) {
      // delegate to parent
      if (out) return out(err);

      // unhandled error
      if (err) {
        // default to 500
        if (res.statusCode < 400) res.statusCode = 500;
        debug('default %s', res.statusCode);

        // respect err.status
        if (err.status) res.statusCode = err.status;

        // production gets a basic error message
        var msg = 'production' == env
          ? http.STATUS_CODES[res.statusCode]
          : err.stack || err.toString();

        // log to stderr in a non-test env
        if ('test' != env) console.error(err.stack || err.toString());
        if (res.headerSent) return req.socket.destroy();
        res.setHeader('Content-Type', 'text/plain');
        res.setHeader('Content-Length', Buffer.byteLength(msg));
        if ('HEAD' == req.method) return res.end();
        res.end(msg);
      } else {
        debug('default 404');
        res.statusCode = 404;
        res.setHeader('Content-Type', 'text/plain');
        if ('HEAD' == req.method) return res.end();
        res.end('Cannot ' + req.method + ' ' + utils.escape(req.originalUrl));
      }
      return;
    }

不过这样的话, 自己定义 404 页面是怎样做到的 https://github.com/visionmedia/express/blob/master/examples/error-pages/index.js#L45

@jiyinyiyong app.get()这个功能是由一个叫router的中间件来处理的 默认创建的代码中有这一行,就是使用这个路由中间件:

app.use(app.router);

app.router的定义在这里:https://github.com/visionmedia/express/blob/master/lib/application.js#L70

// router
this._router = new Router(this); 
this.routes = this._router.map;
this.__defineGetter__('router', function(){
  this._usedRouter = true;
  this._router.caseSensitive = this.enabled('case sensitive routing');
  this._router.strict = this.enabled('strict routing');
  return this._router.middleware;
});

router.middleware的代码:https://github.com/visionmedia/express/blob/master/lib/router/index.js#L32

this.middleware = function router(req, res, next){
  self._dispatch(req, res, next);
};

这个_dispatch方法就是查找是否有注册匹配的路由,如果有则调用相应的函数,否则直接调用next()进入下一个中间件。

@leizongmin 好多代码看得乱了… 这么说所有的 GET POST 都是在同一个 middleware 里的? 那还有比如 404 这种特殊的路由怎样处理的呢?

@jiyinyiyong app.get('/ooxx', function () {});不是注册中间件,而是对中间件app.router进行配置(包括app.post()app.all()等),虽然其工作机制跟middleware差不多,但不要混淆。

@leizongmin 我绕得有点晕了… 我想理一下, 比方说我写了 app.use(..);app.get(...);, 两行代码, 那么 Express 内部的查询过程是怎么样的呢?

我现在能理解是先去找中间件, 中间件可能一般通过 next() 跳出, 跳出之后继续找中间件, 这时遇到作为中间件传的 app.get() 生成的路由… 那这个是不是错了?.. 两者顺序怎么样, 如果遍历中间件找不到是不是调用 connect404 操作了?

真的理解错了… 谢谢指导, 现在明白过来了 原来 app.router 是单独的一个和 middleware 平级的对象 http://nodejs.iteye.com/blog/1594920

app.use(express.logger(...));
app.use(express.bodyParser(...));
app.use(express.cookieParser(...));
app.use(express.session(...));
app.use(app.router);
app.use(express.static(...));
app.use(express.errorHandler(...));
回到顶部