通过简单的JS代码,理解下链式思想

330 阅读4分钟

废话开篇:有时候对于阅读源码难度对我个人而言可能是设计逻辑很难理解,思想达不到那种高度吧,iOS 不管是OC,还是swift 都有 RX的身影,会用,但是对于源码的理解真的很难做精,而且很多的类也是通过部分对象"开枝散叶"而来,所以,根据自身的对他思想的理解简单写个小demo,纯属思路,代码一般。

什么是序列?什么是订阅?

序列:列就是一组、就是集合,序就是顺序。这里啰嗦一句,其实,面向对象编程,其实也是面向过程编程。对象是变量的集合+方法的集合体。那么,如果是面向过程编程,自然就希望代码逻辑清晰,有些时候,为了满足异步的需求往往会添加回调函数来使任务顺序执行。那么,如果代码特别多的情况下,代码的阅读性就会降低。那么搞个任务序列出来是不是就能一目了然了呢?任务序列就是将任务集合在一起,有序的进行执行,这里再添加上优雅的“点语法”,简直就是完美。

订阅:其实,订阅本身个人就可以理解为最终谁来接手任务队列执行完的最后结果。iOS下RAC,对于订阅也有很多区别,比如:热信号订阅(理解成看直播,过去了你就看不到了),冷信号订阅(理解成买饭,你来了,人家才买给你,并且,有多少给你多少)。

简单的 js demo 理解一下

首先创建三个文件:

image.png

wrx.html 文件 简单代码

这里很简单,就是引用了另外的两个js文件,当然,写了一串链式调用的方法。


<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./wrx.js" type="text/javascript"></script>
		<script src="./person.js" type="text/javascript"></script>
	</head>
	<body>
	</body>
	<script>
		var person = new Person();
		//创建person类实例对象,进行显示名字,加载数据,执行登录方法,这里模拟的是异步
                person.wrx.showMyName().loadData().login().next(function(obj){
			console.log(obj);
		});
	</script>
</html>

person.wrx 这里的 wrx 属性将它放在了 Object.prototype.wrx 上,这样其实每个类都会有这样的一个wrx对象存在了。

wrx.js 文件 简单代码

wrx.js 文件主要是进行链式调用的处理及任务的执行。

//这里定义了WRX类
function WRX() {
	//保存上一次任务处理完成的数据
        this.obj = null;
        //保存订阅要执行的回调方法
	var _next = null;
        //保存任务的队列(其实就是数组,队列可以理解为集合跟执行顺序的统一,比如:异步队列、同步队列)
	var _missionQueue = [];
        //下一个任务创建方法,这里做两件事,1、保存任务,2、返回this,目的就是可以继续执行“点语法”
	this.doNextWRXResult = function(cb){
		_missionQueue.push(cb);
		return this;
	}
	//这里可以理解为任务完成进行发布
	this.sendNext = function(obj){
		this.obj = obj;
                //这里需要注意的是,所有任务都结束之后再进行订阅的方法调用,目的是只要任务队列的最终结果。
		if(_missionQueue.length == 0){
			_next(this.obj);
		}
                //因为发布逻辑不管是异步还是同步最后都要走这个函数,那么,进行下一个任务就在这里调用
		this.doMission();
	}
	//这里供外界最后调用,进行其他操作,比如:需要不同的类调用方法时候需要传的参数。
	this.next = function(cb){
		var that = this;
		_next = cb;
                //开始任务执行
		this.doMission();
	}
	//执行任务序列,这个方法放在了 .next 方法后面执行,并且这里执行任务的时候添加了一个定时器,其实不添加也一样,添加的目的是保证任务队列执行是放在当前链式调用所以的函数之后。
	this.doMission = function(){
		if(_missionQueue.length > 0){
			var that = this;
			setTimeout(function(){
				var missionCB = _missionQueue[0];
				_missionQueue.splice(0,1);
				missionCB(that);
			},0);
		}
	}
}

//工厂方法
function FactoryWRX(){
	return new WRX();
}

//绑定 prototype
Object.prototype.wrx = FactoryWRX();

person.js 文件 简单代码

person 对象这里的方法统一用 this.wrx 进行声明的,把方法给了当前对象实例的 wrx 对象,而且方法体也用的是 this.wrx.doNextWRXResult 进行填充,目的是保存到任务队列里面。

function Person() {
	//同步调用
        this.wrx.showMyName = function(){
		return this.wrx.doNextWRXResult(function(wrx){
			wrx.sendNext("WSL");
		});
	}
	
        //模拟异步请求
	this.wrx.loadData = function(){
		return this.wrx.doNextWRXResult(function(wrx){
			setTimeout(function(){
				wrx.sendNext(wrx.obj + "  我不想说了  ");
			},5000);
		});
	}
	
        //模拟异步请求
	this.wrx.login = function(){
		return this.wrx.doNextWRXResult(function(wrx){
			setTimeout(function(){
				wrx.sendNext(wrx.obj + '  登录成功  ');
			},1000);
		});
	}
}

方法执行效果

三个方法执行

image.png

image.png

两个方法执行

image.png

image.png

单次方法执行

image.png

image.png

好了,demo很简单,没啥水平,主要是帮助理解一些编程思想。听说 “勾股定理” 有400种证明方法,但是,提出 “勾股定理” 的只有一次。所以,设计模式是才是打开另一世界的大门。

代码拙劣,大神无笑。