CNode

express 的 app.get() 怎样理解?

Jjiyinyiyong发布于14 年前最后回复14 年前10 回复25173 浏览0 收藏

表示对所谓 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)

L
leizongmin#1·14 年前
/**
 * 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);
  }
});
L
leizongmin#2·14 年前
引用 leizongmin

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

J
jiyinyiyong#3·14 年前
引用 leizongmin

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

J
jiyinyiyong#4·14 年前

终于有点懂了,, 所有被 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

L
leizongmin#5·14 年前
引用 leizongmin

@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()进入下一个中间件。

J
jiyinyiyong#6·14 年前
引用 leizongmin

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

L
leizongmin#7·14 年前
引用 leizongmin

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

J
jiyinyiyong#8·14 年前
引用 leizongmin

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

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

J
jiyinyiyong#9·14 年前
引用 leizongmin

真的理解错了... 谢谢指导, 现在明白过来了 原来 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(...));
L
leizongmin#10·14 年前
引用 leizongmin

@jiyinyiyong 111

参与回复
登录后即可参与回复。登录