原 荐 any-loader JS数据加载器中间件
栏目: JavaScript · 发布时间: 6年前
内容简介:any-loader 旨在为 node.js 和其他的 javascript 提供一个可定制程度较高的数据加载器中间件类库。本身并不实现任何数据加载器的实现逻辑,只界定了数据 流走向的标准接口any-loader 支持并实现了以下编程特性:码云仓库地址:
简介
any-loader 旨在为 node.js 和其他的 javascript 提供一个可定制程度较高的数据加载器中间件类库。本身并不实现任何数据加载器的实现逻辑,只界定了数据 流走向的标准接口 newLoadStrem -> setup -> beforeLoad -> doLoad -> afterLoad
,调用顺序(不可逆),以及此过程中的异常错误处理机制。
any-loader 支持并实现了以下编程特性:
- 基于AOP设计,支持异步(Promise)。
- 中间件形态,不干涉业务逻辑和底层实现。
- 使用OOP进行扩展,使用继承和方法重载,来进行子类的开发,并提供丰富的方法以控制的粒度。
- 接口基于 Promise 封装,向后兼容 async/await 语法
- 数据流(LoadStream)部分,使用 fp 编程,数据流持有的
input
,output
等数据,只在接口中流转,结束后即作废。 Loader 本身无状态,不持有过程数据。
码云仓库地址: https://gitee.com/janpoem/any-loader
设计初衷
在决定将 any-loader 作为独立的项目前,正忙于一个基于 React.js Web 实现的后台文件管理系统,因为前端环境和服务器环境,需要在前端集成比较多的数据接口。
- 一般的 Ajax 拉取文件列表、单个文件、更新文件修改等。
- 前端的 FileReader ,识别和检测用户上传文件的安全性,以及图片和视频客户端生成预览(嗯,现在这些都转移到前端实现了,没必要交给后端做了,以后有空再把这一块开源)。
- 客户端直接上传到 CDN,没必要再从服务器走一趟了,根据文件类型,还要通知 CDN 对文件进行各种处理(如视频转码、压缩分辨率,图片生成缩略图等)。
- 上传完毕,需要更新服务器端,记录文件信息,以及有效的 CDN 资源地址。
前端需要异步调用的地方很多,最初的想法是将功能和资源点接近形成一个加载器组,进行封装管理。可是随着开发的代码增加,就越发发现加载器组控制粒度不够细。
- 随着接口越来越多,应用层面、界面层面的调用代码越来越多,越来越多的结构控制,更别提在不改变调用代码的前提下,去扩展和细化加载器的中间逻辑代码,只能不断的增加应用层的代码量。
- 异步环调用情况更恶劣。项目里有对Ajax的请求封装,但这只适合单次Ajax(适合网站前台)请求,后台的请求,特别是文件管理系统,往往在执行一个操作,往往涉及到一个系列的异步调用环。比如上传到 CDN,要先从服务器端拿到 token ,上传完毕后,还需要将信息保存到服务器端。
- 基于 JS 老掉牙的事件驱动,应用层的代码会臃肿不堪,不断嵌套的事件注册,不利于后续的扩展和开发。
- 缺乏统一调度管理,这里说的调度,即同类接口的并发策略,是等待、取消还是延后等。嗯,是的,当更大程度的使用 React.js ,对于各种数据加载,其实隐性的存在这一个并发调度管理的需求,现有的各种 工具 类库,并没有在这些方面有很好的着力点,可以说完全为零。在C#和 Java 等静态语言有线程安全一说,可是在过去20多年的JS开发中,并没有这个概念。但随着现在前端技术发展的程度,前端的异步调度安全性,成为一个非常重要的内容(特别是Web Worker、Service Worker、大量的 Promise 环境下)。
- 基于 React.js 的一些特性,想将数据加载接口传递进组件内被使用,是一个比较头疼的问题。当然可以选择使用 Redux 等,Redux 开拓了一个全新的编码区间,以解决这方面的问题。但我并不是太喜欢这种动不动就打开一个新的编码空间的做法,太多框架一再用事实告诉我们,如果不解决问题本身,而为了解决某类型问题去开拓一个新的编码区间,最终那个区间只会成为一个无王法、无规范,代码质量差,问题成堆的集中地,所以还是要回到问题本质。
经过一番思索和准备,我决定将 any-loader 作为一个独立的类库来实现。any-loader 不旨在解决实际加载器的业务流程的复杂度,也不提供 Loader 的实现,更不会考虑对任何数据加载方式做封装。any-loader 只定义了一个数据加载流的接口调用顺序,并将足够多的方法和接口进行暴露,提供给子类更多细化调节和扩展的空间。同时,在不改变应用层的调用代码的前提下,随着项目的开发程度和需求细化程度,可以逐步对项目实际的 Loader 进行渐进式的升级和扩展,而不需要一再的去调整应用层的调用代码。
简单示例
class ImageLoader extends Loader { // 默认形态下,input, output 是 {} doLoad({input, output, errors}) { return new Promise((resolve, reject) => { const image = new Image(); image.onload = function(ev) { output.image = this; output.width = this.width; output.height = this.height; resolve(); }; image.onerror = (ev) => { reject(new Error('图片加载失败!')); }; image.src = input.url; }); } } const loader = new ImageLoader(); loader.load({url: 'https://www.oschina.net/build/oschina/components/imgs/header/logo.svg'}).then(({output}) => { }).catch(error => { });
这里定义了一个图片加载器,通过 doLoad 方法的重载,来实现该加载器的具体实现。当然这个例子看起来很简单,市面上大把这样的图片加载器的类库。下来我们接着扩展。
// 我们先定义了一个远程的URL类,或者你的项目本身就有类似的设定 class RemoteURL { constructor() { // .... } toURL() { return '...'; } } // 再定义一个远程的图片类 class RemoteImage { constructor(remoteUrl) { this.url = remoteUrl; // 这是一个RemoteURL的实例 this.isLoad = false; this.image = null; this.error = null; } load(image) { this.isLoad = true; this.image = image; } error(error) { this.error = error; } } class ImageLoader extends Loader { // 我们将 RemoteURL 的实例,作为 LoadStream 的 input newInput(input) { return new RemoteURL(this.mergeArgs(input)); } newOutput(input, output) { // 到这里时,input已经变为 RemoteURL 的实例 return new RemoteImage(input); } // input => RemoteURL, output => RemoteImage doLoad({input, output, errors}) { return new Promise((resolve, reject) => { const image = new Image(); image.onload = function(ev) { output.load(this); resolve(); }; image.onerror = (ev) => { output.error(new Error('图片加载失败!')); reject(output.error); }; image.src = input.toURL(); }); } } // 调用代码 const loader = new ImageLoader(); loader.load({url: 'https://www.oschina.net/build/oschina/components/imgs/header/logo.svg'}).then(({output}) => { }).catch(error => { });
第二个例子中,我们增加了两个中间类,以对ImageLoader 的输入、输出,进行更细的控制。同时,为ImageLoader重载了两个方法,以将输入、输出的实例绑定到ImageLoader 标准流程中去。在应用层调用的代码不变的前提下,通过增加中间层的代码,实现了对Loader更多的控制。
更多例子,后续更新
版本说明
现阶段,不考虑基于类库层面解决并发策略的问题,而在具体的项目里实现的 子类Loader 去简单的管理。
未完,待续。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Docker——容器与容器云
浙江大学SEL实验室 / 人民邮电出版社 / 2015-9-1 / 89.00元
本书从实践者的角度,在讲解Docker高级实践技巧的同时,深入到源代码层次,为读者梳理出Docker容器技术和基于Docker的容器云技术(如Kubernetes)的实现方法和设计思路,帮助读者理解如何在实际场景中利用Docker解决问题并启发新的思考。全书包括两部分,第一部分深入解读Docker容器技术,包括Docker入门、架构总览、Docker容器核心原理解读,以及Docker高级实践技巧;......一起来看看 《Docker——容器与容器云》 这本书的介绍吧!