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中间件的更多相关文章

  1. 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 ...

  2. node.js 中间件

    node.js 中间件 node.js middleware Express middleware body-parser cookie-parser cookie-session cors csur ...

  3. Node.js中间件的使用

    1.中间件 为主要的业务逻辑服务:接收到请求,以及做出响应 应用级中间件.路由级中间件.内置中间件.第三方中间件.错误处理中间件 (1)路由级中间件 路由器的使用 (2)应用级中间件 也称为自定义中间 ...

  4. Node.js Web 开发框架大全《中间件篇》

    这篇文章与大家分享优秀的 Node.js 中间件模块.Node 是一个服务器端 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用程序,编写能够处 ...

  5. 【epub.js|翻译|原创】开源中间件epub.js的使用及其中文文档

    epub是最流行的电子书规范之一,网络上对于Java Web有不少合适的方法来解析和呈现,但是关于epub.js的介绍比较少(尽管github上已经2K星了),更多的是概念性的内容,如: epub.j ...

  6. JS第三方中间件的延伸

    js中间件 当我们在编写业务代码时候,我们无法避免有些业务逻辑复杂而导致业务代码写得又长又乱,如果再加上时间紧凑情况下写出来的代码估计会更让人抓狂.以至于我们一直在寻求更好的架构设计和更好的代码设计, ...

  7. Node.js学习笔记——Node.js开发Web后台服务

    一.简介 Node.js 是一个基于Google Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.Node.j ...

  8. Node.js Express 框架

    Node.js Express 框架 Express 简介 Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP ...

  9. Node.js Express框架

    Express 介绍 Express是一个最小的,灵活的Node.js Web应用程序框架,它提供了一套强大的功能来开发Web和移动应用程序. 它有助于基于Node Web应用程序的快速开发.下面是一 ...

随机推荐

  1. LayUI table表格控件 如何显示 对象中的属性(针对Mybatis的级联查询--一对一情况)

    1.entity如下: 2.Mybatis的Mapper.xml文件如下 <resultMap id="BaseResultMapPlus" type="dicIt ...

  2. Linux 常用命令三 touch mkdir

    一.touch命令 创建一个文件: wang@wang:~/workpalce/python$ ls wang@wang:~/workpalce/python$ .txt wang@wang:~/wo ...

  3. Codeforces Round #479 (Div. 3)解题代码

    A. Wrong Subtraction #include <bits/stdc++.h> using namespace std; int main() { int n,k; cin&g ...

  4. 牛客小白月赛5-J-时间(time) (简单模拟)

    题目描述 Apojacsleam是一个喜欢特殊时刻的人. 他定义了一个时刻,若电子表显示ab:ba(24小时制),则该时刻为“回文时刻”(可以有前导零).例如00:00就是回文时刻. 给定一个时刻,求 ...

  5. XmlPullParser接口详述

    带*的是非常重要的函数.点击有说明.setInputgetDepthisWhitespacegetTextisEmptyElementTaggetAttributeCountgetAttributeV ...

  6. 转-解决Mysql ERROR 1045 (28000): Access denied for user 'root'@'localhost'问题

    ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)   Red Hat Enterpr ...

  7. sed练习简记

    1. 使用多命令选项-e sed -e 'command1' -e 'command2' -e 'command3' 在/etc/passwd文件中搜索root.nobody或mail [root@s ...

  8. AJPFX实列判断一个字符串是不是对称字符串

    import java.util.Scanner; /** *        判断一个字符串是否是对称字符串 */ public class StringDemo { public static vo ...

  9. AJPFX关于代码块的总结

    代码块:        {                执行语句;        }(1) 当出现在局部位置时, 为局部代码块.        局部位置: 如语句块中, 函数中, 构造代码块中, 静 ...

  10. 实现上下全屏幕屏滚动效果js

    ---恢复内容开始--- 详情见代码 第一步:首先添加3个js文件: 1.http://cdn.staticfile.org/jquery/1.8.3/jquery.min.js 2.http://c ...