觀察者模式又稱發佈-訂閱模式
,它定義對象間的一種一對多的依賴關係,當一個對象發生改變的時候,所依賴它的對象都能獲得通知。例如:咱們訂閱了一個欄目,當欄目有新文章的時候,它會自動通知全部訂閱它的人。javascript
代碼實現:
簡單的代碼實現:html
class Radio { constructor() { this.state = 0; this.observers = []; } setState(state) { this.state = state; this.notifyingObservers(); } addObserver(observer) { this.observers.push(observer); } notifyingObservers() { const state = this.state; this.observers.forEach(observer => { observer.update(state); }); } } class People { constructor(name) { this.name = name; } update(content) { console.log(`我是${this.name},我接受到更新了,更新內容:${content}`); } } // 建立訂閱者 const peopleA = new People('小A'); const peopleB = new People('小B'); const peopleC = new People('小C'); // 添加發布者 const radio = new Radio(); // 訂閱 radio.addObserver(peopleA); radio.addObserver(peopleB); radio.addObserver(peopleC); // 發佈者發佈 radio.setState('十月份最熱歌單發佈了'); radio.setState('十一月份最新原創歌單發佈了');
Radio
),它有更新內容(setState
)、添加訂閱者(addObserver
)、以及觸發全部訂閱者(notifyingObservers
);People
),他有本身的我的信息(如:name
),以及接受到通知後所須要執行的動做(updata
);notifyingObservers
方法,將全部的observers
的update
都觸發了固然,實際上,咱們上的每個訂閱者都有這個update,當這個update不知足功能需求的時候,咱們一樣能夠將實例出來的訂閱者單獨設置update; 如:java
peopleA.update = function(content) { // 新代碼 }
以上就是一個簡單的觀察者模式的例子node
代碼案例:react
<button id="btn">點擊</button> <script> $('#btn').click(function() { console.log('btn被點擊'); }) </script>
$('#btn')
的click事件,當$('#btn')
的click被咱們點擊觸發,函數收到觸發信息,並自執行。 那麼這個函數就是觀察者(訂閱者),$('#btn')
的click事件就是觀察目標(發佈者)。代碼案例:git
function loadImage(url) { return new Promise(function(resolve, reject) { let image = document.createElement('img'); image.onload = function () { resolve(image); } image.onerror = function () { reject('圖片加載失敗'); } image.src = url; }); } const src = 'http://imgsrc.baidu.com/image/c0%3Dpixel_huitu%2C0%2C0%2C294%2C40/sign=ad13ee4af0f2b211f0238d0ea3f80054/2e2eb9389b504fc26849383ceedde71190ef6df1.jpg' const img = loadImage(src); img.then(function (img) { console.log('width', img.width); return img }).then(function (img) { console.log('height', img.height); });
https://github.com/xieranmaya/blog/issues/3
這篇文檔。promise.then會把內部的函數添加到一個callback的數組內,等異步執行完成以後在進行一次調用該函數。每個.then會返回一個新的promise。github
代碼案例:數組
class EventEmitter() { constructor() { this.events = {}; } // 訂閱事件 on(type, listener) { if (!this.events) { this.events = Object.create(null); } if (this.events[type]) { this.events[type].push(listener) } else { this.events[type] = [listener]; } } // 觸發執行 emit(type, ...args) { if (this.events[type]) { this.events[type].forEach(fn => fn.call(this, ...args)); } } // 解綁 off(type, listener) { id (this.events[type]) { this.events[type] = this.events[type].filter(fn => { return fn !== listener; }); } } } const myEmitter = new EventEmitter(); myEmitter.on('log', function() {console.log('111111')}); myEmitter.emit('log');
解讀:這個就和第一個案例有點類似,咱們在jq中見過這樣的頁面事件寫法:promise
$('id').on('click', function() { // 事件代碼 });
這個就是一種事件觸發器,在nodejs裏面大量採用了事件觸發器的方法。詳情能夠去看nodejs裏面的EventEmitter
方法,就能夠大致理解他的機制了。
同理,咱們也能夠明白react裏面的生命週期等mvvm框架,裏面大量採用了觀察者模式。它們都是定義了一個個鉤子,等狀態達到的時候我就觸發相對應的鉤子,執行相對應的代碼。框架
總之,觀察者模式在javascript中的使用是很是普遍的。其低耦合的特色方便在多人開發的複雜項目中,能提升效率,使代碼的維護性大大提高。