溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

node.js學習筆記之淺談觀察者模式

發(fā)布時間:2020-07-23 02:20:24 來源:網(wǎng)絡 閱讀:1091 作者:lixiaoyu1223 欄目:web開發(fā)

在我的理解中,觀察者模式,又叫發(fā)布/訂閱模式,是一種是一種很便捷的用于不同模塊之間相互通信的一種方式,類似于事件又不同于事件。

在我目前的理解中,觀察者模式應該有三個部分組成,發(fā)布者,訂閱者,管理平臺,發(fā)布者發(fā)布信息到管理平臺,管理平臺收集到信息之后分發(fā)給訂閱者,用更淺白的語言來形容我對觀察者模式的理解就是函數(shù)調用,在不同模塊之間通過函數(shù)調用進行通信。

言語之間不太好解釋,還是來看看代碼,可以更快的理解我所說的意思,先看管理平臺是如何工作的:

let event = [];
class Test{
	static addEvent(type,fn){
		if(!event[type]){
			event[type] = [fn];
		}else{
			event[type].push(fn);
		}
	}
	static dispath(type){
		let s = [] ,i=1;
		while (arguments[i])
		{
			s.push(arguments[i]);
			i++;
		}
		if(!event[type]){
			console.error('no Event!');
		}else{
			for(let i = 0;i<event[type].length;i++){
				event[type][i](...s);
			}
		}
	}
}

我這里起名字的時候是用了Event的那一套名字,但和Event那一套其實沒有什么關系,完全可以換成不同的名字。

看上面的代碼:

let event = [];

這是一個數(shù)組,用來存放訂閱者的信息,也就是訂閱的事件類型,和觸發(fā)函數(shù),最終所形成的樣式是這樣的:

[
    'type1' : [fn1,fn2,fn3],
    'type2' : [fn4],
    'type3' : [fn5,fn6]
]

實際上就是有三個訂閱者訂閱type1,觸發(fā)事件分別為fn1,fn2,fn3,后面等同。當發(fā)布者發(fā)布type1的時候,就會調用函數(shù)fn1,fn2,等等。

因為訂閱者須要提前訂閱才能接收到被訂閱的內容,所以,我們先看訂閱者是如何訂閱的:

static addEvent(type,fn){
		if(!event[type]){
			event[type] = [fn];
		}else{
			event[type].push(fn);
		}
	}

在node.js中我們聲明了一個類名為Test,里面有個靜態(tài)方法 addEvent,兩個參數(shù),第一個是訂閱的事件類型,第二個是觸發(fā)函數(shù),當還沒有人訂閱該事件的時候,就先創(chuàng)建該事件的函數(shù)空間,實際上就是一個數(shù)組,把事件名當索引,把觸發(fā)事件存到該索引的元素下,如果已經有人訂閱了該事件,就直接把觸發(fā)事件push到對應索引的元素下。這樣就可以記錄下所有訂閱者訂閱的事件了。


然后是發(fā)布者發(fā)布事件:

static dispath(type){
		let s = [] ,i=1;
		while (arguments[i])
		{
			s.push(arguments[i]);
			i++;
		}
		if(!event[type]){
			console.error('no Event!');
		}else{
			for(let i = 0;i<event[type].length;i++){
				event[type][i](...s);
			}
		}
	}

這也是一個靜態(tài)函數(shù),是用來把發(fā)布者發(fā)布的消息分發(fā)到每一個訂閱者,while循環(huán)中是對參數(shù)的處理,把除第一個參數(shù)之外的所有參數(shù)集中到一個數(shù)組里,方面后面展開,這樣可以還原到發(fā)布消息時的參數(shù)順序,方面訂閱者更好的接收參數(shù),然后就是在所有的訂閱者中找到第一個參數(shù)(也就是發(fā)布者發(fā)布的事件)所對應的所有觸發(fā)函數(shù),然后循環(huán)調用一次并把除事件之外的參數(shù)傳過去。


這樣的話,管理平臺就組建好了。下面就是訂閱,因為不先訂閱是不可能收到發(fā)布者發(fā)布的消息的。

Test.addEvent('A',function (name,age){
	console.log('hello,this is "A" Event 1,has arg:','name:',name,'age:',age);
});
Test.addEvent('B',function (num){
	console.log('hello,this is "B" Event 2,has arg:',num);
});
Test.addEvent('C',function (obj){
	console.log('hello,this is "C" Event 3,has arg:',obj);
});
Test.addEvent('D',function (arr){
	console.log('hello,this is "D" Event 4,has arg:',arr);
});
Test.addEvent('E',function (date){
	console.log('hello,this is "E" Event 5,has arg:',date);
});

上面我們訂閱了五個事件,每個事件所要接收的參數(shù)類型都不一樣。并且訂閱類型A須要接收兩個參數(shù),

訂閱是不是很簡單?好吧,其實發(fā)布者更簡單:

Test.dispath('A','xiaoming',17);
Test.dispath('B',123);
Test.dispath('C',{say:'hello word'});
Test.dispath('D',[1,2,3]);
Test.dispath('E',new Date());

發(fā)布事件ABCDE,后面跟上發(fā)布的內容,然后訂閱者就可以接發(fā)布時的順序來接收參數(shù)。在項目中的不同模塊之間進行通信就變得非常簡單了。

到了這里,我想大家應該也都發(fā)現(xiàn)了我所說的訂閱/發(fā)布 實際上就是函數(shù)調用是怎么回事了,訂閱者把將要因事件而被觸發(fā)的函數(shù)通過函數(shù)調用傳到管理平臺上,發(fā)布者把須要發(fā)布的事件也通過函數(shù)調用傳到管理平臺上,然后管理平臺則根據(jù)不同的事件調用不同的函數(shù)。

代碼不夠精練,格式不夠標準......

好吧,完了。

------------------------------------------------------------------------------------

另外,記錄一點和該話題沒多大關系但用到的一點內容,就是參數(shù)傳遞那一塊,因為管理平臺不能確定發(fā)布者會傳多少參數(shù)進來,所以用到了Node.js的一個特性:arguments,在node.js中不論函數(shù)有有沒有聲明接收的參數(shù),每個函數(shù)中都會有一個局部變量arguments,它是一個object對象,會把外界調用該函數(shù)時所傳進來的參數(shù)整合進來,然后把傳參的順序做為屬性,比如上面的A事件,在管理平臺的dispath函數(shù)中arguments就是這個樣子的:

{
    '0' : 'A',
    ‘1’:‘xiaoming’,
    '2' : 17
}

對象直接用  ...  這個符號拆分的話會報錯,所以我把arguments用while重新組合成了數(shù)組,然后用 ...符號來拆分數(shù)組再進行參數(shù)傳遞。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI