Last active
April 18, 2017 08:46
-
-
Save pjchender/c3fd1408b4fb1f8c0640c5c849672671 to your computer and use it in GitHub Desktop.
[JavaScript][RxJS] 30 天精通 RxJS (04): 什麼是 Observable ?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const arr = [1, 2, 3] | |
// 原生的 array iterator | |
let nativeIterator = arr[Symbol.iterator]() | |
nativeIterator.next() // {value: 1, done: false} | |
nativeIterator.next() // {value: 2, done: false} | |
nativeIterator.next() // {value: 3, done: false} | |
nativeIterator.next() // {value: undefined, done: true} | |
// 利用 function 的方法建立 Array Iterator | |
function IteratorFromArray (arr) { | |
if (!(this instanceof IteratorFromArray)) { | |
throw new Error('請用 new IteratorFromArray( )') | |
} | |
this._array = arr | |
this._cursor = 0 | |
} | |
// instance method | |
IteratorFromArray.prototype.next = function () { | |
return this._cursor < this._array.length ? | |
{ cursor: this._cursor, value: this._array[this._cursor++], done: false} : | |
{done: true} | |
} | |
let functionIterator = new IteratorFromArray(arr) | |
functionIterator.next() // {cursor: 0, value: 1, done: false} | |
functionIterator.next() // {cursor: 1, value: 2, done: false} | |
functionIterator.next() // {cursor: 2, value: 3, done: false} | |
functionIterator.next() // {done: true} | |
// 利用 ES6 class 建立 Iterator | |
class arrayIterator { | |
constructor (array) { | |
this._array = array | |
this._cursor = 0 | |
} | |
// next function | |
next(){ | |
return (this._cursor < this._array.length) ? {value: this._array[this._cursor++], done: false} : {done: true} | |
} | |
// map iterator | |
map(callback){ | |
const iterator = new arrayIterator(this._array) | |
// return 一個物件,裡面包含 next 這個 method | |
return { | |
next(){ | |
const { done, value } = iterator.next() | |
return { | |
done: done, | |
value: done ? undefined : callback(value) | |
} | |
} | |
} | |
} | |
} | |
let classIterator = new arrayIterator(arr) | |
let mapIterator = classIterator.map(value => value * 3) | |
classIterator.next() // {value: 1, done: false} | |
classIterator.next() // {value: 2, done: false} | |
classIterator.next() // {value: 3, done: false} | |
classIterator.next() // {done: true} | |
// use mapItertor | |
mapIterator.next() // {value: 3, done: false} | |
mapIterator.next() // {value: 6, done: false} | |
mapIterator.next() // {value: 9, done: false} | |
mapIterator.next() // {value: undefined, done: true} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 建立 Class:使用 ES6 的 Class | |
**/ | |
class Producer { | |
// constructor | |
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) | |
}) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 建立 Class:使用 function constructor | |
**/ | |
function Producer() { | |
if(!(this instanceof Producer)){ | |
// 如果 this 不是 Producer 的 instance(表示忘了用 "new") | |
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) | |
}) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 建立物件實例 | |
const egghead = new Producer() | |
function listener1 (message) { | |
console.log(message + 'from listener1') | |
} | |
function listener2 (message) { | |
console.log(message + 'from listener2') | |
} | |
// 註冊監聽 | |
egghead.addListener(listener1) | |
egghead.addListener(listener2) | |
// 當 notify 執行時,listener1 和 listener2 就會被通知 | |
egghead.notify('A new Course!!') |
[Iterator Pattern]
觀念
Iterator Pattern
雖然很單純,但同時帶來了兩個優勢
-- 第一它漸進式取得資料的特性可以拿來做延遲運算(Lazy evaluation),讓我們能用它來處理大資料結構。
-- 第二因為 iterator 本身是序列,所以可以實作所有陣列的運算方法像 map, filter... 等!延遲運算(Lazy evaluation)
,或說call-by-need
,是一種運算策略(evaluation strategy),簡單來說我們延遲一個表達式的運算時機直到真正需要它的值在做運算。
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
[觀察者模式(Observer Pattern)]
觀念
觀察者模式簡單來說就是「我們可以對某件事註冊監聽,並在事件發生時,自動執行我們註冊的監聽者(listener)。」
檔案
檔案包含:createConstructorClass.js, createConstructorFunction.js, notify.js
Run on JSFiddle
參考資料
30 天精通 RxJS (04): 什麼是 Observable ?