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 结束
每一个中间件执行权利传递给下一个中间件并等待其结束以后又回到当前并做别的事情,方法非常巧妙。
原文链接:https://www.cnblogs.com/wjd2221/p/7364221.html
JS第三方中间件的延伸的更多相关文章
- Node.js  + Express中间件详解
		
使用中间件 Express是一种路由和中间件Web框架,它具有自己的最小功能:Express应用程序本质上是一系列中间件函数调用. 中间件函数是可以访问请求对象 (req),响应对象(res)以及应用 ...
 - 高性能的js第三方库——lodash、 Underscore、async、md5及moment
		
背景:为了实现某些功能,如:数据排序.分组.筛选.深拷贝等,自己写的函数或网上搜索处理的转换函数质量无法保证,这时直接使用成熟的js第三方库是首选. *注:“framework(框架)”,“libra ...
 - express第三方中间件研究之bodyParser中间件
		
转载至:http://www.cnblogs.com/lianer/p/5178693.html 接触nodejs已有一段时间了,但最近才开始落实项目,于是使用express应用生成器生成了一个应用. ...
 - Nest.js  添加中间件
		
Docs: https://docs.nestjs.com/middleware 创建中间件 logger.middleware.ts import { Injectable, NestMiddlew ...
 - Node.js 第三方包的安装、升级、卸载,以及包依赖管理
		
本地安装: npm install package-name 全局全装: npm install -g package-name 举个栗子 全局安装 React项目的脚手架 npm install ...
 - node.js 的 中间件 初理解
		
听说中间件还挺重要,下面梳理一下初认识: 中间件是什么?简单说说http请求服务的过滤,当交给函数处理之前先交给它处理.匹配后会终止,要想再匹配,得加: next. 中间件能解决什么问题?检测用户登录 ...
 - js第三方
		
1.0 https://github.com/aui/artDialog 2.0 前端开发仓库 http://code.ciaoca.com/ 3.0 打赏 https://github.com/gr ...
 - 小程序中怎么引入wepy.js第三方toast组件
		
1.先安装组件 npm install wepy-com-toast --save 2.引入wepy和toast import wepy from 'wepy' import Toast from ' ...
 - 字符串编码js第三方类库text-encoding
		
GITHUB地址:https://github.com/BCode001/text-encoding
 
随机推荐
- 批处理(cmd)的学习记录
			
批处理的使基本使用 Command Introduction Example set 设置环境变量 set name="小明" call 启动应用程序 rem 解释说明,可通过 ...
 - JAVA基础-面向对象05
			
一.面向对象的引入 解决问题的时候,首先要会分析思路,这个思路就是我们生活中解决一个问题的方法步骤: 有了思路之后,再把思路使用java代码来解决: 但是 计算总分的需求变了 分析:原来在一个程序中, ...
 - 【WEB基础】HTML & CSS 基础入门(4)列表及其样式
			
前面 网页中漂亮的导航.整齐规范的文章标题列表和图片列表等等.这些都是离不开HTML里一个重要的元素----列表,在HTML中有无序列表.有序列表和定义列表三种类型.其中,无序列表应用最为广泛,下面, ...
 - Codeforces - 466C - Number of Ways - 组合数学
			
https://codeforces.com/problemset/problem/466/C 要把数据分为均等的非空的三组,那么每次确定第二个分割点的时候把(除此之外的)第一个分割点的数目加上就可以 ...
 - Navicat Premium连接服务器数据库
			
解决Navicat 连接服务器失败的问题 由于服务器的安全问题,有些东西默认是关闭的.就像远程连接服务器的数据库一样,如果默认是每个IP都能访问,安全性就会大大降低,甚至没有安全性可言.但是由于项目需 ...
 - python __builtins__ credits类 (15)
			
15.'credits', 信用 class _Printer(builtins.object) | interactive prompt objects for printing the licen ...
 - linux 问题一 apt-get install 被 lock
			
问题: sudo apt-get install vim E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporari ...
 - scikit-learning教程(四)选择合适的估计量
			
选择正确的估计 解决机器学习问题的最困难的部分通常是找到合适的工作量. 不同的估计器更适合于不同类型的数据和不同的问题. 下面的流程图旨在给用户一些关于如何处理关于哪些估计器尝试您的数据的问题的粗略指 ...
 - h5-20-文件操作-拖放文件
			
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
 - django 相关问题
			
和数据库的连接 session的实现 django app开发步骤 python环境准备 数据库安装 model定义 url mapping定义 view定义 template定义 如何查看数据库里的 ...