rxjs入門4之rxjs模式設計

長安城下翩翩少年發表於2019-05-13

觀察者模式 (Observer Pattern)

rxjs入門4之rxjs模式設計

觀察者模式其實在日常編碼中經常遇到,比如DOM的事件監聽,程式碼如下

function clickHandler(event) {
    console.log('user click!');
}
document.body.addEventListener('click', clickHandler)

簡而言之:觀察者模式就如同上程式碼,有一個事件源‘dom 的click事件’ 也就是abservable,有一個觀察者abserver clickHandler函式,有一個訂閱機制(addEventLister),當dom的click事件觸發時候,會通過訂閱機制通知abserver 執行函式clickHandler函式。

下面是構建一個觀察者模式的簡單例子

function Producer() {

    // 這個 if 只是避免使用者不小心把 Producer 當作函式來呼叫
    if(!(this instanceof Producer)) {
      throw new Error('請用 new Producer()!');
      // 仿 ES6 行為可用: throw new Error('Class constructor Producer cannot be invoked without 'new'')
    }

    this.listeners = [];
}

// 加入監聽的方法
Producer.prototype.addListener = function(listener) {
    if(typeof listener === 'function') {
        this.listeners.push(listener)
    } else {
        throw new Error('listener 必須是 function')
    }
}

// 移除監聽的方法
Producer.prototype.removeListener = function(listener) {
    this.listeners.splice(this.listeners.indexOf(listener), 1)
}

// 傳送通知的方法
Producer.prototype.notify = function(message) {
    this.listeners.forEach(listener => {
        listener(message);
    })
}

接下來建立例項

var egghead = new Producer(); 
// new 出一個 Producer 例項叫 egghead

function listener1(message) {
    console.log(message + 'from listener1');
}

function listener2(message) {
    console.log(message + 'from listener2');
}

egghead.addListener(listener1); // 註冊監聽
egghead.addListener(listener2);

egghead.notify('A new course!!') // 當某件事情方法時,執行
//a new course!! from listener1
//a new course!! from listener2

迭代器模式 (Iterator Pattern)

Iterator 是一個物件,它的就像是一個指標(pointer),指向一個資料結構併產生一個序列(sequence),這個序列會有資料結構中的所有元素(element)。
迭代者(Iterator,也稱為“迭代器”)指的是能夠遍歷⼀個資料集合的物件,因為資料集合的實現⽅式很多,可以是⼀個陣列,也可以是⼀個樹形結構,也可以是⼀個單向連結串列……迭代器的作⽤就是提供⼀個通⽤的介面,讓使⽤者完全不⽤關⼼這個資料集合的具體實現⽅式。

自己實現簡單的迭代器

function IteratorFromArray(arr) {
    if(!(this instanceof IteratorFromArray)) {
        throw new Error('請用 new IteratorFromArray()!');
    }
    this._array = arr;
    this._cursor = 0;   
}

IteratorFromArray.prototype.next = function() {
    return this._cursor < this._array.length ?
        { value: this._array[this._cursor++], done: false } :
        { done: true };
}

補充 - ES6 生成器

生成器是一種返回迭代器的函式,通過function關鍵字後的星號(*)來表示,函式中會用到新的關鍵字yield。星號可以緊挨著function關鍵字,也可以在中間新增一個空格

// 生成器
function *createIterator() {
    yield 1;
    yield 2;
    yield 3;
}
// 生成器能像正規函式那樣被呼叫,但會返回一個迭代器
let iterator = createIterator();
console.log(iterator.next().value); // 1
console.log(iterator.next().value); // 2
console.log(iterator.next().value); // 3


function *createIterator(items) {
    for (let i = 0; i < items.length; i++) {
        yield items[i];
    }
}
let iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: 3, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
// 之後的所有呼叫
console.log(iterator.next()); // "{ value: undefined, done: true }"

Observable 其實就是這兩個 Pattern 思想的結合,Observable 具備生產者推送資料的特性,同時能像序列,擁有序列處理資料的方法(map, filter...)!

更簡單的來說,Observable 就像是一個序列,裡面的元素會隨著時間推送。

相關文章