Unix Pipes to Javascript Pipes

Unix Pipes

Unix管道扫描稿php

1

简单样例:前端

$ netstat -apn | grep 8080jquery

相信这个你们常常使用,这里就不细说了。webpack

那么管道基本思想是什么呢?git

  • 让每一个程序只完成一件事,并将其作好(do one thing and do it well),完成一个新任务,新建一个程序,而不是在旧程序中添加新特性
  • 标准化每一个程序的输入和输出,让任意符合标准的程序能够串在一块儿(write programs to work together)
  • 设计和创造软件,而不是架构或系统

NodeJS Stream

NodeJS中引入流概念来解决I/O异步问题,若是没有Stream,咱们可能要这么写代码:github

var http = require('http'); var fs = require('fs'); // 著名的回调地狱又来了 var server = http.createServer(function (req, res) { fs.readFile(__dirname + '/data.txt', function (err, data) { res.end(data); }); }); server.listen(8000); 

但有了Stream,咱们就能够更优雅的编写代码:web

var http = require('http'); var fs = require('fs'); var server = http.createServer(function (req, res) { var stream = fs.createReadStream(__dirname + '/data.txt'); // 把两个管子接起来 stream.pipe(res); }); server.listen(8000); 

想添加一个新功能?要用gzip压缩文件?OK,能够这么写:ajax

var http = require('http'); var fs = require('fs'); var oppressor = require('oppressor'); var server = http.createServer(function (req, res) { var stream = fs.createReadStream(__dirname + '/data.txt'); // 将三个管子连起来 stream.pipe(oppressor(req)).pipe(res); }); server.listen(8000); 

Back-end to Font-end

随着EventStream、Gulp、Webpack管道在后端的盛行,管道逐渐从后端向前端渗透,如Angular、Vuejs。咱们在Q.js、高可扩展数据层组件DB.core中大量使用了管道过滤器(Pipe-And-Filter)模式。后端

2

(webpack的核心:管道式插件)架构

那么前端的管道又是怎样的呢?让咱们看看DB.core中的例子。

Pipes in DB.core

DB的设计初衷在于解决CGI拉取的通用性问题,例如:区分正确和错误逻辑、通用错误逻辑处理、登录态通用处理。但DB却难以复用,由于咱们发现每一个业务的通用性各不相同,一般咱们新起一个业务老是要将DB复制下来后作大量侵入式修改,才能适用于新的业务要求。而在齐齐互动视频中,咱们例如管道过滤器模式重构了咱们的DB。 具体请参见:https://github.com/miniflycn/db

问题在哪里?
  • Rule of Simplicity: Design for simplicity; add complexity only where you must.
  • Rule of Parsimony: Write a big program only when it is clear by demonstration that nothing else will do.

DB干了太多事情,致使每次干一件事情就要插入各类代码。经过管道过滤器模式,将每件事情拆成独立的过滤器,每一个过滤器只作一件事,但将一件事情作到极致。

单一功能原则(Single responsibility principle)规定每一个类都应该有一个单一的功能,而且该功能应该由这个类彻底封装起来。全部它的(这个类的)服务都应该严密的和该功能平行(功能平行,意味着没有依赖)。

马丁把功能(职责)定义为:“改变的缘由”,而且总结出一个类或者模块应该有且只有一个改变的缘由。一个具体的例子就是,想象有一个用于编辑和打印报表的模块。这样的一个模块存在两个改变的缘由。第一,报表的内容能够改变(编辑)。第二,报表的格式能够改变(打印)。这两方面会的改变由于彻底不一样的原由而发生:一个是本质的修改,一个是表面的修改。单一功能原则认为这两方面的问题事实上是两个分离的功能,所以他们应该分离在不一样的类或者模块里。把有不一样的改变缘由的事物耦合在一块儿的设计是糟糕的。

——from wiki

前端经常使用的管道过滤器模式基本实现
/** * _apply * @param {Array} handles 处理函数列队,每个是一个管子 * @param {*} data 要处理的数据 * @param {Object} options 可选参数 * @param {Function} cb 处理后回调 */ _apply: function (handles, data, options, cb) { var i = 0, l = handles.length, res = data; for (i; i < l; i++) { res = handles[i].call(this, res, options); // if handle return false, just break if (res === false) return; } cb(res); }, 
db.core完整实现
var $ = require('jquery'); /** * DB * @class * @param {Object} options this is just a $.ajax setting *  @param {Array} options.errHandles *  @param {Array} options.succHandles *  @param {Function} options.succ *  @param {Function} options.err */ function DB(options) { this._init(options); } $.extend(DB.prototype, { _init: function (options) { this.errHandles = options.errHandles || []; this.succHandles = options.succHandles || []; this.errHandles.unshift.apply(this.errHandles, DB.options.errHandles || []); this.succHandles.unshift.apply(this.succHandles, DB.options.succHandles || []); options = $.extend({}, DB.options || {}, options); this.options = options; }, _wrap: function (options) { var self = this; options.success = function (data) { // you may want to modify this line for judging error or success data.retcode === 0 ? self._apply(self.succHandles, data, options, options.succ) : self._apply(self.errHandles, data, options, options.err); }; options.error = function (data) { self._apply(self.errHandles, data, options, options.err); }; return options; }, _apply: function (handles, data, options, cb) { var i = 0, l = handles.length, res = data; for (i; i < l; i++) { res = handles[i].call(this, res, options); // if handle return false, just break if (res === false) return; } cb(res); }, /** * ajax * @param {Object} options this is just a $.ajax setting *  @param {Function} options.succ *  @param {Function} options.err */ ajax: function (options) { options = this._wrap($.extend({}, this.options, options)); !options.data && (options.data = options.param); $.ajax(options); } }); $.extend(DB, { httpMethod: function (options) { var db = new DB(options); return function (opt) { db.ajax(opt); return this; }; }, extend: jQuery.extend, // default options options: {} }); module.exports = DB; 

这样咱们就能够把之前的各类业务数据检测,甚至是数据组装都放在succHandles和errHandles进行。这是咱们在齐齐项目中使用的一个例子,能够看见,咱们把数据组装也放在了DB层进行。

1

相关文章
相关标签/搜索