订阅-发布(观察者)模式在前端控件初始化时的运用

56 篇文章 5 订阅
4 篇文章 0 订阅
前些时候在使用公司的地址控件的时候遇到一个问题。在同一个页面,我有三处地方调用了这个地址控件。这个地址控件初始化的时候要使用AJAX从后台获取所有的地址数据下来。结果发现发起了三次对地址数据的请求。

一、原始版本:

示意代码类似这样。
function A(name){
	this.name = name ;
	this.init();
}
A.prototype={
	init:function(name){
		//在回调函数中拿到初始化的这个对象
		var self = this;
		//拿到数据之后的回调函数
		var callback = function(data){
			console.log('这是初始化的'+self.name+'的回调函数');
			console.log(data);
			A.data = data;
		}
		//判断要获取的数据是否已经获取过。没获取过则ajax获取。
		if(A.data){
			callback(A.data);
		}else{
			$.ajax({
				url : 'data.json',
				noLoad: true,
				success: callback
			});
		}

	}
}

可以看到这个控件里,我们做了基本的对数据是否存在的判断,这样在页面再次调用的时候不会再次请求数据。

然后我们调用两次:
//第一次调用
var a = new A('1a');
//第二次调用
var aa = new A('2a');

输出:

通过输出发现我们实现了两次实例化。并且在回调中都拿到了我们实例化的对象中的数据,从而可以对这个控件进行一些其他的操作。
但是,当我打开网络面板,发现数据请求了两次:


是init()函数里的判断没有起到作用吗?
不是,其实是因为第二次实例化控件的时候,第一个的AJAX请求的数据还没有拿到, 所以第二次实例化的时候还会走AJAX流程。
那个判断的作用体现在数据拿到之后,再次调用此控件或调用此控件里的init()方法的时候,比如我再new一个A,就不会再次请求数据了,如下图。


从上面的运行情况看。这个控件显然是不完善的。我们一次实例化多次此控件,就会发起多个AJAX请求, 如果请求的数据很大的话或网络不佳,会严重影响网页体验。并且即使某一个实例中的AJAX获取到了数据,其他的实例依然会等待自己调用的AJAX获取的数据。

二、使用订阅-发布(观察者)模式完善:
要把这个控件完善起来,我们需要实现:
1.只在第一次实例化该控件的时候调用AJAX获取数据。
2.AJAX获取到数据之后执行每一个实例中的回调函数。也就是说,要在回调函数中拿到实例对象。

在这种情况下,使用订阅-发布模式无疑是很合适的。
每次实例化这个控件的时候,就订阅一下。然后拿到数据之后一次性发布出来。
看过设计模式相关的书的想必对订阅-发布模式(观察者模式)不会陌生。像我们使用的浏览器的各种事件就属于这个模式。
可以自己写一套事件机制,也可以使用jQuery那一套事件机制。这里,我就直接使用 jQuery的事件机制了。
修改代码如下:
function A(name){
	this.name = name ;
	this.init();
}
A.prototype={

	init:function(name){
		//在回调函数中拿到初始化的这个对象
		var self = this;
		//拿到数据之后的回调函数
		var callback = function(event,data){
			console.log('这是初始化的'+self.name+'的回调函数');
			console.log(data);
			A.data = data;
		}
		//判断要获取的数据是否已经获取过。没获取过则ajax获取。
		if(A.data){
			callback(A.data);
		}else{
			if(!A.ajaxing){
				this.getAjaxData();
			}
			//订阅
			$(document).on('dataOk',callback);			
		}

	},
	getAjaxData:function(){
		A.ajaxing = true;
		$.ajax({
			url : 'data.json',
			noLoad: true,
			success: function(data){
				//触发我们定义的这个事件,并传递ajax获取到的数据
				//发布
				$(document).trigger('dataOk',[data]);
				A.ajaxing = false;
			}
		});
	}
}


//第一次调用
var a = new A('1a');
//第二次调用
var aa = new A('2a');

我们定义了一个叫做‘dataOk’的事件,在没获取到数据的情况下,每次实例化这个控件者会给这个事件绑定一个回调函数。然后当AJAX获取到结果之后,使用trigger方法触发这个'dataOk'事件,并将AJAX获取到的数据传递给这个事件的回调函数。注意这里对jQuery事件机制的使用。

输出结果:

请求次数:


功能基本实现

那么,本文就讲了使用发布-订阅模式在要用AJAX获取数据来初始化的控件中的运用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值