摘要:響應式命令式這兩種編程風格的思維方式是完全相反的。第二種方式是工人主動去找工人索取生產手機所要的零件,然后生產一臺完整的手機,這兩種方式就對應的響應式和命令式。
angular2中內置了rxjs,雖然框架本身并沒有強制開發者使用響應式風格來組織代碼,但是從框架開發團隊的角度可以看出他們必然是認同這種編程風格的。rxjs本質是基于函數式編程的響應式風格的庫,函數式相對于面向對象來說更加抽象,響應式的思維方式和命令式的思考方式又截然相反,所以導致大多數的開發者開始接觸時覺得非常不適應,認為門檻太高,其實不然,只要思維方式能轉變,你會覺得響應式是更加順其自然的事情。響應式涉及的知識點很多,這篇文章只能做到管中窺豹,讓大家在感性上對它有一個認識。
面向對象 vs 函數式抽象層級不同:簡單來說,面向對象抽象了物,而函數式抽象了行為。最簡單的例子:
function Person(name, age) { this.name = name; this.age = age; } Person.prototype.ageAfterYears = function(years) { console.log(this.age + years); } var john = new Person("John", 18);
面向對象的方式
john.ageAfterYears(5) // 23;
函數式的方式:
function getAge(baseAge) { return (obj) => console.log(obj.age + baseAge); } const ageAfterYears = getAge(5); ageAfterYears(john); // 23;
這段代碼很簡單,但足以說明問題,使用面向對象的方式時,我們直接調用person類的方法,計算出實例的年齡,我們會很在乎這個對象上是否提供這么一個方法。但使用函數式時,ageAfterYears函數并不在乎傳入的對對象上是否有那個方法,只需要傳入的對象有上age屬性,它就可以得一個結果,我們更在乎的是這種行為是否正確,例如計算函數的行為是加,而不是減,或者其它。
響應式 vs 命令式這兩種編程風格的思維方式是完全相反的。假設一個生產手機的過程,第一種方式是工人 A 先處理零件,然后交給工人 B, 工人 B 接收后生產出一臺手機。第二種方式是工人 B 主動去找工人 A 索取生產手機所要的零件,然后生產一臺完整的手機,這兩種方式就對應的響應式和命令式??梢钥闯?,響應式更適合于流水線式的生產,因為它節省了大量的溝通成本。尤其重要的一點是工人 B的行為是‘懶’的,它不會主動的去爭取任務,而是一直在等待任務的到來。在程序中,數據就是我們產品的零件,因此也適合這種流水線式的處理。假如我們需要控制用戶在一個按鈕上每秒最多只能點擊一次,看下面這段代碼:
使用命令式:
var count = 0; var rate = 1000; var lastClick = Date.now() - rate; var button = document.querySelector("button"); button.addEventListener("click", () => { if(Date.now() - lastClick >= rate) { console.log(`Clicked ${++count} timers`); lastClick = Date.now(); } });
使用響應式:
var button = button.querySelector("button"); Rx.Observable.fromEvent(button, "click") .throttleTime(1000) .scan(count => count + 1, 0) .subscribe(count => console.log(`Click ${count} times`));
從代碼上可以看出,命令式的代碼量更大,而響應式的只有區區幾行,當然你可以說這是因為使用了rxjs封裝的庫,但更為重要的是在命令式的代碼中變量的數量更多,尤為糟糕的是這些變量相對于主邏輯來說處于‘全局‘的位置,而javascript中全局變量是魔鬼,我們不得不隨時小心這些定時炸彈。
上面已經提到過響應式的處理過程是’懶‘的,除此之外,它的優點可以概括如下
所有數據處理的過程使用操作符的全部都是純函數,它們只是單純的接收輸入,產生輸出,并不會對輸入的值做出任何改變。
rxjs實現的 Observable 是一個可以產生多個值序列,是一個 push 類型的系統,這和 pull 類型的函數系統有很大的不同。
push vs pull這里使用 pull 和 push 來描述值的生產者和消費者之間是如何發生聯系的,它們是兩種完全不同的協議。
在pull的系統中,值的消費決定什么時間從生產者上獲取數據,生產者本身并不關心數據什么時間分發給消費者。
每一個javascript函數都可以看作一個 pull 類型的系統。函數可以產生值,但這是通過調用者主動調用函數,函數運行產生出值返回給調用者的方式進行的,所以可以理解為調用者主動去函數上拉取了值。
ES2015中介紹另外兩種 pull 類型的系統,generator函數 和 iterator。對于它們來講,遍歷器對象的 next 方法可以視作值的消費者,通過iterator.next()可以獲取到多個值。
Producer | Consumer | |
---|---|---|
pull | 被動:當被調用時產生值 | 主動:決定何時發起調用 |
push | 主動:按自身的設置產生值 | 被動:響應接收到的值 |
在push的系統中,生產者決定什么時候發送值給消費者,消費者并不知道什么時候可以接收到值。
ES6中的 promise 就是一個非常典型的 push 系統,promise 將 resolve 的結果傳遞給注冊在它內部的回調函數,這與普通的函數有很大的不同,回調函數何時可以接收到數據完全取決于 promise 什么時間向它傳遞數據。
rxjs的 Observable 也是一種 push 類型的系統,一個 Observable 可以產生多個值,然后推送給它的訂閱者。
Function 是一個 ‘懶’ 的求值過程,只有在被調用時它才會同步的返回一個值給調用者。
generator 也是一個 ’懶‘ 的求值過種,在遍歷的過程中同步的返回0個或多個值給調用者。
Promise 經過運算后可能產生一個值,當然也可能產生一個錯誤。
Observable 也是一個‘懶’的求值過程,當它被訂閱后可以同步或者異步的產生出0個或者無限多個值給調用者,這個過程將一直持續到訂閱被取消或者流結束。
今天先寫到這里,沒有過多的代碼, 更沒有涉及到angular中如何去應用響應式,個人認為寫代碼的過程其實不難,難的是思維方式的轉換,希望能從文字的描述上給大家一點啟發。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/97265.html
摘要:從這個系列的第一章開始到第五章,基于的響應式編程的基礎知識基本上就介紹完了,當然有很多知識點沒有提到,比如,等,不是他們不重要,而是礙于時間精力等原因沒辦法一一詳細介紹。 從這個系列的第一章開始到第五章,基于rxjs的響應式編程的基礎知識基本上就介紹完了,當然有很多知識點沒有提到,比如 Scheduler, behaviorSubject,replaySubject等,不是他們不重要,...
摘要:響應式組件上節中錯誤的把添加到了中,實際中它返回的是一個,先調整過來。將這兩條流合并成一條請求流。利用上面實現的方法,可以很方便的拿到響應流,即。由于不同于,請求和響應一一對應的很好,所以這里可能需要一定的條件來拿到請求對應的響應。 上回搭建了一個組件以及它所依賴的服務的基本結構,這節接著它繼續。另外從本節開始,統一采用rxjs6的風格,6和5在寫法上最大的不同就是棄用鏈式調用,而采用...
摘要:最近有同學在使用時總是不能如愿拿到自己想要的數據,說到底還是沒有能把思維從命令式的習慣中轉換過來。響應式的編程風格中,數據應該在流內完成轉換,合并,過濾,而不是取出來,一頓操作再丟回流里。 最近有同學在使用rxjs時總是不能如愿拿到自己想要的數據,說到底還是沒有能把思維從命令式的習慣中轉換過來。 Observable !== 異步 && Observable !== 同步 如題,請默念...
摘要:它有三個方法,用來通知下一個值是什么方法在上產生錯誤時通知觀察者,方法用來通知觀察者當前流上的值已經發射完畢。除此之外在我們不需要訂閱時,觀察者還應該能夠安全的退出。 上次說了響應式中使用的設計模式,今天我們主要來看rxjs中實現響應式的三大件,Observable, subject 和 Subscription; Observable--可觀測序列 在第一節中介紹過 push 類型的...
摘要:而數組里則是為每一個值運行一次映射函數,無論這個值何時加入,然后把它返回到里。上一章翻譯連載第章異步的函數式上輕量級函數式編程你不知道的姊妹篇原創新書移動前端高效開發實戰已在亞馬遜京東當當開售。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關于譯者:這是一個流淌著滬江血液的純粹工程:認真,是 ...
閱讀 2234·2021-11-17 09:33
閱讀 2774·2021-11-12 10:36
閱讀 3395·2021-09-27 13:47
閱讀 884·2021-09-22 15:10
閱讀 3485·2021-09-09 11:51
閱讀 1392·2021-08-25 09:38
閱讀 2757·2019-08-30 15:55
閱讀 2608·2019-08-30 15:53