RxJS 笔记 04

参考 简书原文 作者:readilen

1 Observer Pattern 观察者模式

典型例子: DOM的事件监听

function clickHandler(event) {
console.log('user click!');
}

document.body.addEventListener('click', clickHandler)

手写练习

function Producer() {
  // 这个 if 只是避免使用者不小心把 Producer 当作函数来调用
  if (!(this instanceof Producer)) {
    // 仿 ES6 行为可用
    throw new Error('请用 new Producer()!');
  }

  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)
  })
}
class Producer {
  constructor() {
    this.listeners = [];
  }

  addListener(listener) {
    if (typeof listener === 'function') {
      this.listeners.push(listener)
    } else {
      throw new Error('listener 必须是 function')
    }
  }

  removeListener(listener) {
    this.listeners.splice(this.listeners.indexOf(listener), 1)
  }

  notify(message) {
    this.listeners.forEach(listener => {
      listener(message)
    })
  }
}

2 Iterator Pattern 迭代器模式

它就像是一个指针(pointer),指向一个资料结构并产生一个序列(sequence)
这个序列会有资料结构中的所有元素(element)

练习

var arr = [1,2,3];

var iterator = arr[Symbol.iterator]();

iterator.next()
// {value: 1, done: false}
interator.next()
// {value: 2, done: false}
interator.next()
// {value: 3, done: false}
interator.next()
// {value: undefined, done: true}

JS到了ES6才有原生的Iterator

JS的采用functional的做法,在取得最后一个元素之后
执行next永远都回传 {done:true, value:undefined}

最后一个元素前 : {done:true, value:elem}
最后一个元素之后: {done:false, value:undefined}

练习

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

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

  next() {
    return this._cursor < this._array.length ?
      { value: this._array[this._cursor++], done: false } :
      { done: true }
  }
}
2-1 优势
  • 渐进式取得资料的特性可以拿来做延迟运算(Lazy evaluation), 让我们能用它处理大资料结构
  • 本事序列,所以可以实作所有阵列的运算方法 像 map, filter…等

延迟迭代器,call-by-need

function* getNumbers(words) {
  for (let word of words) {
    if (/^[0-9]+$/.test(word)) {
      yield parseInt(word, 10);
    }
  }
}

const interator = getNumbers('30 天精通 RxJS (04)');

interator.next();
// {value: 3, done:false}
interator.next();
// {value:0, done:false}
interator.next();
// {value:0, done:false}
interator.next();
// {value:4, done:false}
interator.next();
// {value:undefined, done:true}

map迭代器

class InteratorFromArray {
  constructor(arr) {
    this._array = arr;
    this._cursor = 0;
  }
  next() {
    return this._cursor < this._array.length ?
    {value: this._array[this._cursor++], done:false} :
    {done:true}
  }
  map(callback) {
    const iterator = new InteratorFromArray(this._array);
    return {
      next: () => {
        const {done, value} = iterator.next();
        return {
          done: done,
          value: done ? undefined : callback(value)
        }
      }
    }
  }
}

let interator = new InteratorFromArray([1,2,3]);
let newInterator = interator.map(value => value + 3);

newInterator.next();
// {value:4, done:false}
newInterator.next();
// {value:5, done:false}
newInterator.next()
// {value:6, done:false}
newInterator.next()
// {value:undefined, done:true}

3 Observer Pattern 观察者模式 & Iterator Pattern 迭代器模式

Observer 跟 Iterator 共通的特性

  • 都是 渐进式(progressive) 的取得资料

Observer 跟 Iterator 区别

  • Observer 是生产者(Producer)推送资料(push)
  • Iterator 是消费者(Consumer)要求资料(pull)

4 Observable 简介

Observable 其实就是这两个 Pattern 思想的结合,

  1. 具备生产者推送资料的特性,
  2. 同时能像序列,拥有序列处理资料的方法(map, filter…)!