计算机领域的 Pipeline 通常认为起源于 Unix。最初 Douglas Mcllroy 发现很多时候人们会将 shell 命令的输出传递给另外一个 shell 命令,因此就提出了 Pipeline 这一概念。后来同在贝尔实验室的大牛 Ken Thompson 在 1973 年将其实现,并使用 | 作为 pipe 的语法符号:
$ ls -l | grep key | less
如此优雅而又实用的 Pipeline 很快在各种操作系统中传播开来。
简单来说,Pipeline 一般具有如下特点:
- 各个子过程高内聚,专注于解决特定问题,Simple & Sharp
- 所有子过程具有一致的接口,例如从标准输入读取数据,正常结果输出到标准输出,异常结果输出到标准错误
- 能够通过一定形式将子过程组合起来解决复杂问题,例如 pipe
事实上,Pipeline 作为化整为零、去繁就简的重要手段,在前端中也有诸多应用。
Middleware Pipeline
NodeJS 框架 Express 在 1.0 版本中引入的 Middleware Pipeline 可以说为 Express 的流行居功至伟。透过下面简单几行代码,你就能感受到它散发的优雅气息:
express()
.use(bodyParser.json())
.use(cookieParser())
.use(session(sessionOptions))
.use('api', apiRoutes)
.use(errorHandler);
或许对于很多后来人来说,并不觉得这有什么精巧独到之处。但在 NodeJS 刚刚开始流行的那个蛮荒年代,大多数人写的还是流水账一样的过程式代码,好一些的会去整理一些工具函数以供抽象和复用:
var srv = http.createServer(function (req, res) {
req.parsedBody = bodyParser(req);
req.parsedCookie = cookieParser(req);
session(req, res, function (err) {
if (err) {
errorHandler(err);
return;
}
// routes
});
});
相比之下,我们可以明显看出 Middleware 的几个优势:
- 代码简练、符合直觉。这是一个很重要的优势,因为代码的大部分生命周期内都是由程序员在维护,符合直觉的代码更容易被理解,在维护和定位问题时能够更有效率
- 合理的错误处理。任意 Middleware 出现问题,会越过后续所有普通 Middleware,直接由 Error Middleware 进行处理
事实上,还有一个更为重要的优势:标准化,为解决高层次问题提供了良好基础。通过将 API 执行路径上的各个环节抽象为中间件,然后再将中间件划分为通用逻辑(Pre-processing / Post-processing 等