wap网站开发协议,做电器哪个网站好,上海优秀网站设计,做做做网站上一节实现了 express 的中间件#xff0c;这一节来实现错误处理中间件
执行某一步出错了#xff0c;统一规定调用 next 传递的参数就是错误信息
先看 express 实现的demo
const express require(express);
const app express();app.use(/, (re…上一节实现了 express 的中间件这一节来实现错误处理中间件
执行某一步出错了统一规定调用 next 传递的参数就是错误信息
先看 express 实现的demo
const express require(express);
const app express();app.use(/, (req, res, next) {console.log(中间件1);// next();next(中间件1出错了);
});app.use(/, (req, res, next) {console.log(中间件2);next();// next(中间件2出错了);
});app.use(/, (req, res, next) {console.log(中间件3);next();// next(中间件3出错了);
});app.get(/,(req, res, next) {console.log(路由1);next();},(req, res, next) {res.end(出错了 *****);}
);app.listen(3000, () {console.log(server start 3000);console.log(在线访问地址http://localhost:3000/);
});然后去访问http://localhost:3000/ 错误处理中间价里面必须要有 4 个 参数取函数的长度放到栈的最底下
app.use((err, req, res, next) {res.end(err);
})下面实现处理逻辑
router/index.js
const url require(url);
const Route require(./route);
const Layer require(./layer);
const methods require(methods);function Router() {// 维护所有的路由this.stack [];
}Router.prototype.route function (path) {// 产生 routelet route new Route();// 产生 layer 让 layer 跟 route 进行关联let layer new Layer(path, route.dispatch.bind(route));// 每个路由都具备一个 route 属性稍后路径匹配到后会调用 route 中的每一层layer.route route;// 把 layer 放到路由的栈中this.stack.push(layer);return route;
};methods.forEach((method) {Router.prototype[method] function (path, handlers) {// 1.用户调用 method 时需要保存成一个 layer 当道栈中// 2.产生一个 Route 实例和当前的 layer 创造关系// 3.要将 route 的 dispatch 方法存到 layer 上let route this.route(path);// 让 route 记录用户传入的 handler 并且标记这个 handler 是什么方法route[method](handlers);};
});Router.prototype.use function (path, ...handlers) {// 默认第一个是路径后面是一个个的方法路径可以不传if (typeof path function) {handlers.unshift(path);path /;}// 如果是多个函数需要循环添加层for (let i 0; i handlers.length; i) {let layer new Layer(path, handlers[i]);// 中间件不需要 route 属性layer.route undefined;this.stack.push(layer);}
};Router.prototype.handle function (req, res, out) {console.log(请求到了);// 需要取出路由系统中 Router 存放的 layer 依次执行const { pathname } url.parse(req.url);let idx 0;let next (err) {// 遍历完后没有找到就直接走出路由系统if (idx this.stack.length) return out();let layer this.stack[idx];if (err) {console.log(统一对中间件跟路由错误处理);// 找错误处理中间件if (!layer.route) {// 如果是中间件自己处理layer.handle_error(err, req, res, next);} else {// 路由则跳过继续携带错误向下执行next(err);}} else {// 需要判断 layer 上的 path 和当前请求路由是否一致一致就执行 dispatch 方法if (layer.match(pathname)) {// 中间件没有方法可以匹配不能是错误处理中间件if (!layer.route) {if (layer.handler.length ! 4) {layer.handle_request(req, res, next);} else {next();}} else {// 将遍历路由系统中下一层的方法传入// 加速匹配如果用户注册过这个类型的方法在去执行if (layer.route.methods[req.method.toLowerCase()]) {layer.handle_request(req, res, next);} else {next();}}} else {next();}}};next();
};module.exports Router;layer.js
function Layer(path, handler) {this.path path;this.handler handler;
}Layer.prototype.match function (pathname) {if (this.path pathname) {return true;}// 如果是中间件进行中间件的匹配规则if (!this.route) {if (this.path /) {return true;}// /aaaa/b 需要 /aaaa/ 才能匹配上return pathname.startsWith(this.path /);}return false;
};
Layer.prototype.handle_error function (err, req, res, next) {if (this.handler.length 4) {// 调用错误处理中间件return this.handler(err, req, res, next);}next(err); // 普通的中间件
};
Layer.prototype.handle_request function (req, res, next) {this.handler(req, res, next);
};
module.exports Layer;route.js
const Layer require(./layer);
const methods require(methods);function Route() {this.stack [];// 用来描述内部存过哪些方法this.methods {};
}Route.prototype.dispatch function (req, res, out) {// 稍后调用此方法时回去栈中拿出对应的 handler 依次执行let idx 0;console.log(this.stack-----, this.stack);let next (err) {// 如果内部迭代的时候出现错误直接到外层的 stack 中err out(err);// 遍历完后没有找到就直接走出路由系统if (idx this.stack.length) return out();let layer this.stack[idx];console.log(dispatch-----, layer.method);if (layer.method req.method.toLowerCase()) {layer.handle_request(req, res, next);} else {next();}};next();
};
methods.forEach((method) {Route.prototype[method] function (handlers) {console.log(handlers-----, handlers);handlers.forEach((handler) {// 这里的路径没有意义let layer new Layer(/, handler);layer.method method;// 做个映射表this.methods[method] true;this.stack.push(layer);});};
});module.exports Route;测试demo
const express require(./kaimo-express);
const app express();app.use(/, (req, res, next) {console.log(中间件1);next();// next(中间件1出错了);
});app.use(/, (req, res, next) {console.log(中间件2);// next();next(中间件2出错了);
});app.use(/, (req, res, next) {console.log(中间件3);next();// next(中间件3出错了);
});app.get(/,(req, res, next) {console.log(路由1);next();},(req, res, next) {res.end(出错了 *****);}
);// 错误处理中间价
app.use((err, req, res, next) {console.log(错误处理中间价-----, err);res.end(err);
});app.listen(3000, () {console.log(server start 3000);console.log(在线访问地址http://localhost:3000/);
});