js中间件
js中间件
当我们在编写业务代码时候,我们无法避免有些业务逻辑复杂而导致业务代码写得又长又乱,如果再加上时间紧凑情况下写出来的代码估计会更让人抓狂。以至于我们一直在寻求更好的架构设计和更好的代码设计,这是一个没有终点的求知之路,但是在这条路上会越走越好。
在前端,我们可以借用这种思想通过before和after函数来实现:
Function.prototype.before = function(fn){//函数处理前执行fn
var self = this;
return function(){
fn.call(this);
self.apply(this, arguments);
}
}
Function.prototype.after = function(fn){//函数处理后执行fn
var self = this;
return function(){
self.apply(this, arguments);
fn.call(this);
}
}
实现思路是对被处理的函数通过闭包封装在新的函数里,在新的函数内部按照顺序执行传入的参数fn和被处理的函数。
1 举个例:
用户提交表单数据之前需要用户行为统计,代码应该是这样写:
function report(){
console.log('上报数据');
}
function submit(){
console.log('提交数据');
}
submit.before(report)(); //提交之前执行report
//结果: 上报数据
// 提交数据
从代码可以看出已经把统计和数据提交业务隔离起来,互不影响。
但是如果提交数据之前,需要数据验证并且依据验证结果判断是否能提交,怎么做?这里要改动before函数,看下代码:
Function.prototype.before = function(fn){//函数处理后执行fn
var self = this;
return function(){
var res = fn.call(this);
if(res)//返回成功则执行函数
self.apply(this, arguments);
}
}
function report(){
console.log('上报数据');
return true;
}
function validate(){
console.log('验证不通过');
return false;
}
function submit(){
console.log('提交数据');
}
submit.before(report).before(validate)();
//结果:
// 验证不通过
function report(){
console.log('上报数据');
return true;
}
function validate(){
console.log('验证通过');
return true;
}
function submit(){
console.log('提交数据');
}
submit.before(report).before(validate)();
//结果:
// 验证通过
// 上报数据
// 提交数据
上面的例子如果很复杂会出现很长的链式,后期维护也很容易看晕,并且before和after也没有考虑到异步操作,显然还是有些不足的,那么还有没有其他解决办法呢,既能隔离业务,又能方便清爽地使用~我们可以先看看其他框架的中间件解决方案。
2 express
express是非常轻量的框架,express是集合路由和其他几个中间件合成的web开发框架,koa是express原班人马重新打造一个更轻量的框架,所以koa已经被剥离所有中间件,甚至连router中间件也被抽离出来,任由用户自行添加第三方中间件。解析express的写法
express的中间件写法如下:
var express = require('express');
var app = express();
app.use(function(req, res, next) {
console.log('数据统计');
next();//执行权利传递给
});
app.use(function(req, res, next) {
console.log('日志统计');
next();
});
app.get('/', function(req, res, next) {
res.send('Hello World!');
});
app.listen(3000);
//整个请求处理过程就是先数据统计、日志统计,最后返回一个Hello World!
从上图来看,每一个“管道”都是一个中间件,每个中间件通过next方法传递执行权给下一个中间件,express就是一个收集并调用各种中间件的容器。
中间件就是一个函数,通过express的use方法接收中间件,每个中间件有express传入的req,res和next参数。如果要把请求传递给下一个中间件必须使用 next() 方法。当调用res.send方法则此次请求结束,node直接返回请求给客户,但是若在res.send方法之后调用next方法,整个中间件链式调用还会往下执行,因为当前hello world所处的函数也是一块中间件,而res.send只是一个方法用于返回请求。
3 参照express我们可以仿写
我们可以借用中间件思想来分解我们的前端业务逻辑,通过next方法层层传递给下一个业务。做到这几点首先必须有个管理中间件的对象,我们先创建一个名为Middleware 的对象:
function Middleware(){
this.cache = [];
}
Middleware通过数组缓存中间件。下面是next和use 方法:
Middleware.prototype.use = function(fn){
if(typeof fn !== 'function'){
throw 'middleware must be a function';
}
this.cache.push(fn);
return this;
}
Middleware.prototype.next = function(fn){
if(this.middlewares && this.middlewares.length > 0 ){
var ware = this.middlewares.shift();
ware.call(this, this.next.bind(this));
}
}
Middleware.prototype.handleRequest = function(){//执行请求
this.middlewares = this.cache.map(function(fn){//复制
return fn;
});
this.next();
}
我们用Middleware简单使用一下:
var middleware = new Middleware();
middleware.use(function(next){console.log(1);next();})
middleware.use(function(next){console.log(2);next();})
middleware.use(function(next){console.log(3);})
middleware.use(function(next){console.log(4);next();})
middleware.handleRequest();
//输出结果:
//1
//2
//3
//
4没有出来是因为上一层中间件没有调用next方法,我们升级一下Middleware 高级使用
var middleware = new Middleware();
middleware.use(function(next){
console.log(1);next();console.log('1结束');
});
middleware.use(function(next){
console.log(2);next();console.log('2结束');
});
middleware.use(function(next){
console.log(3);console.log('3结束');
});
middleware.use(function(next){
console.log(4);next();console.log('4结束');
});
middleware.handleRequest();
//输出结果:
//1
//2
//3
//3结束
//2结束
//1 结束
每一个中间件执行权利传递给下一个中间件并等待其结束以后又回到当前并做别的事情,方法非常巧妙。
js中间件的更多相关文章
- 64。node.js 中间件express-session使用详解
转自:http://jinjiakarl.com/2018/06/09/node-js-%E4%B8%AD%E9%97%B4%E4%BB%B6express-session%E4%BD%BF%E7%9 ...
- node.js 中间件
node.js 中间件 node.js middleware Express middleware body-parser cookie-parser cookie-session cors csur ...
- Node.js中间件的使用
1.中间件 为主要的业务逻辑服务:接收到请求,以及做出响应 应用级中间件.路由级中间件.内置中间件.第三方中间件.错误处理中间件 (1)路由级中间件 路由器的使用 (2)应用级中间件 也称为自定义中间 ...
- Node.js Web 开发框架大全《中间件篇》
这篇文章与大家分享优秀的 Node.js 中间件模块.Node 是一个服务器端 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用程序,编写能够处 ...
- 【epub.js|翻译|原创】开源中间件epub.js的使用及其中文文档
epub是最流行的电子书规范之一,网络上对于Java Web有不少合适的方法来解析和呈现,但是关于epub.js的介绍比较少(尽管github上已经2K星了),更多的是概念性的内容,如: epub.j ...
- JS第三方中间件的延伸
js中间件 当我们在编写业务代码时候,我们无法避免有些业务逻辑复杂而导致业务代码写得又长又乱,如果再加上时间紧凑情况下写出来的代码估计会更让人抓狂.以至于我们一直在寻求更好的架构设计和更好的代码设计, ...
- Node.js学习笔记——Node.js开发Web后台服务
一.简介 Node.js 是一个基于Google Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.Node.j ...
- Node.js Express 框架
Node.js Express 框架 Express 简介 Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP ...
- Node.js Express框架
Express 介绍 Express是一个最小的,灵活的Node.js Web应用程序框架,它提供了一套强大的功能来开发Web和移动应用程序. 它有助于基于Node Web应用程序的快速开发.下面是一 ...
随机推荐
- JVM从理论到实践
这里实践不是指动手写JVM,而是动手做实验,结合日常工作相关的部分,理论与实践结合从而对这块知识有更深入的认识. 随着Java10的到来,JVM这块也有不少调整改进,网上大部分内容都是过时或大部分开发 ...
- shell 与 空格
shell脚本中,不能随意添加空格,否则出错: 1,=等号两边必须无空格.否则出错.如i =$1和i= $1都是错的.但是在()内部不限制如for ((i= 1;i < 3;i= i+1))是正 ...
- baiduTemplate 基本知识总结
html <div id="tem1"></div> <div id="tem2"></div> <!-- ...
- 解决weblogic页面和控制台乱码问题
转自:https://blog.csdn.net/u010995831/article/details/53283746 之前一直有碰到weblogic各种乱码问题,要不就是页面乱码,要不就是控制台乱 ...
- bzoj 4585: [Apio2016]烟火表演【左偏树】
参考:https://blog.csdn.net/wxh010910/article/details/55806735 以下课件,可并堆部分写的左偏树 #include<iostream> ...
- 实现自己的ArrayList
最近在学习数据结构和算法,书上有个ArrayList的简单实现,写的很不错. package cn.sp.test4; import java.util.Iterator; import java.u ...
- 《Windows核心编程系列》十三谈谈在应用程序中使用虚拟内存
在应用程序中使用虚拟内存 Windows提供了以下三种机制对内存进行操控: 一:虚拟内存.最适合来管理大型对象数据或大型结构数组. 二:内存映射文件.最适合用来管理大型数据流,以及在同一机 器上运行的 ...
- 11.Flask-钩子函数
在Flask中钩子函数是使用特定的装饰器的函数.为什么叫做钩子函数呢,是因为钩子函数可以在正常执行的代码中,插入一段自己想要执行的代码,那么这种函数就叫做钩子函数. before_first_requ ...
- 数据结构 - 顺序队列的实行(C语言)
数据结构-顺序队列的实现 1 顺序队列的定义 线性表有顺序存储和链式存储,队列作为一种特殊的线性表,也同样存在这两种存储方式.我们先来看队列的顺序存储结构. 队列的顺序储存结构:用数组存储队列,为了避 ...
- AC自动机 HDOJ 2222 Keywords Search
题目链接 题意:每个文本串的出现次数 分析:入门题,注意重复的关键字算不同的关键字,还有之前加过的清零. 新模板,加上last跑快一倍 #include <bits/stdc++.h> ...