yaofly2012 / note

Personal blog
https://github.com/yaofly2012/note/issues
44 stars 5 forks source link

expressjs-sourceCode-Layer #126

Open yaofly2012 opened 4 years ago

yaofly2012 commented 4 years ago

layer.js

一、什么是Layer?

Layer是个执行者

二、构造函数Layer

function Layer(path, options, fn) {
  if (!(this instanceof Layer)) {
    return new Layer(path, options, fn);
  }

  debug('new %o', path)
  var opts = options || {};

  this.handle = fn;
  this.name = fn.name || '<anonymous>';
  this.params = undefined;
  this.path = undefined;
  this.regexp = pathRegexp(path, this.keys = [], opts);

  // set fast path flags
  this.regexp.fast_star = path === '*'
  this.regexp.fast_slash = path === '/' && opts.end === false
}
  1. Layer是个构造函数,支持工厂函数方式调用。
  2. express模块文件的结构
    • Module dependencies
    • Module variables
    • Module exports
yaofly2012 commented 4 years ago

Layer.prototype.handle_error

Layer.prototype.handle_error = function handle_error(error, req, res, next) {
  var fn = this.handle;

  if (fn.length !== 4) {
    // not a standard error handler
    return next(error);
  }

  try {
    fn(error, req, res, next);
  } catch (err) {
    next(err);
  }
};
  1. error作为第一个参数,有点类似nodejs的回调风格;
  2. this.handle的形参数量是固定的,必须4个,要求规范化异常处理handler的格式;
  3. 采用try-catch捕获this.handle的抛出的异常,并通过next(error)方式处理异常。
yaofly2012 commented 4 years ago

Layer.prototype.handle_request

Layer.prototype.handle_request = function handle(req, res, next) {
  var fn = this.handle;

  if (fn.length > 3) {
    // not a standard request handler
    return next();
  }

  try {
    fn(req, res, next);
  } catch (err) {
    next(err);
  }
};
  1. this.handle定义要求没那么苛刻了,只要形参不多于3个就行(4个视为异常处理handler);
  2. 采用try-catch捕获this.handle的抛出的异常,并通过next(error)方式处理异常。
yaofly2012 commented 4 years ago

Layer.prototype.match

匹配路径字符串,并记录路径参数。 path-to-regexp包要看看

Layer.prototype.match = function match(path) {
  var match
  // `null`和`void 0`是无效参数
  if (path != null) {
    // fast path non-ending match for / (any path matches)
    if (this.regexp.fast_slash) {
      this.params = {}
      this.path = ''
      return true
    }

    // fast path for * (everything matched in a param)
    if (this.regexp.fast_star) {
      this.params = {'0': decode_param(path)}
      this.path = path
      return true
    }

    // match the path
    match = this.regexp.exec(path)
  }

  if (!match) {
    this.params = undefined;
    this.path = undefined;
    return false;
  }

  // store values
  this.params = {};
  this.path = match[0]

  var keys = this.keys;
  var params = this.params;

  for (var i = 1; i < match.length; i++) {
    var key = keys[i - 1];
    var prop = key.name;
    var val = decode_param(match[i])

    if (val !== undefined || !(hasOwnProperty.call(params, prop))) {
      params[prop] = val;
    }
  }

  return true;
};
  1. decode_param(val)函数

    function decode_param(val) {
    if (typeof val !== 'string' || val.length === 0) {
    return val;
    }
    
    try {
    return decodeURIComponent(val);
    } catch (err) {
    if (err instanceof URIError) {
      err.message = 'Failed to decode param \'' + val + '\'';
      err.status = err.statusCode = 400;
    }
    
    throw err;
    }
    }
  2. decodeURIComponent操作如果发生异常,则给error对象添加个status属性,这个在哪里使用?

项目中的异常处理是否也可采用这种模式?