響應式編程101

Reactive Programming 101

Orginal from : The introduction to Reactive Programming you’ve been missing

Reactive Programming 響應式編程

Reactive programming is programming with asynchronous data streams.
響應式編程是異步數據流
這不是什麼新概念,一個點擊事件都是一個異步事件流,你可以觀察並且做一些副作用。
數據流可以在任何地方,變量,用戶輸入,屬性,caches,數據結構。
在往上,你可以對流做一些更改,合流,截流,改道,篩選。combine, create and filter。

一個流是一些列隨時間正在進行的事件。會發出3種信號,值,錯誤,完成。
這裏寫圖片描述
這些發出的事件被我們異步地捕捉,定義3個觸發函數分別對應3個信號(值,錯誤,完成)。返回對應的函數時觸發對應的參數。
有時候我們只需要注意返回信號的觸發函數,而不需要其他信號的觸發函數。
監聽流的行爲叫做訂購(subscribing)。監聽函數定義爲觀察者(observers).
流被觀察,叫做觀察者設計模式(Observer Design Pattern)。

舉例做一個記錄點擊數的按鈕,在大部分響應式庫裏,流通常綁定函數。
當觸發這些函數時,會返回一個新的流。流和新流之間互不干擾。
這裏的流是clickStream,新流是counterStream。

clickStream: ---c----c--c----c------c-->
               vvvvv map(c becomes 1) vvvv
               ---1----1--1----1------1-->
               vvvvvvvvv scan(+) vvvvvvvvv
counterStream: ---1----2--3----4------5-->

觸發map(f)函數(返回新流)時,會替換對應值,這裏替換c爲1。
scan(g)函數會相加之前的值在這個流上(map函數觸發的新流),
最終兩個函數觸發完以後,返回counterStream流。

爲了體現響應式編程的優點,創建一個雙擊事件流,這個流會把大於2次以上的點擊全部計算成雙擊。
原理如下
這裏寫圖片描述
灰色區域就是對流的修改,也就是3個函數。
先對擊數做提取,假設以250mm爲界限,提取出對應的擊數。
然後把擊數替換成數值
最後做一個filter,把>2的篩選出來。

Example 實際案例

選用JS和RxJS作爲工具。

以Twitter推薦follow爲例,這個部分建議要follow的人。
這裏寫圖片描述
重點分析:
- 在啓動時,從api中讀取用戶信息並顯示3個建議
- 刷新時,加載其他3個建議
- 點擊x關閉時,對應建議消失,並出現新的建議
- 每一行顯示3個建議的信息和其連接

在啓動時,從api中讀取用戶信息並顯示3個建議
簡化成 1)request 2)get responce 3)render responce
把請求想象成流,一開始是這樣

--a------|->
a 就是api請求 `'https://api.github.com/users'`

當一個請求事件發生時,有兩個信息,when and what,
何時該執行 就是請求發生時的時間,
what 就是請求內容,這裏是一串url。

在Rx*裏面,創建一個流的官方名字是觀察者,但是直接叫流(stream)更合適。

var requestStream = Rx.Observable.just('https://api.github.com/users');

訂閱流,以便操作,然後用Ajax回調函數,處理這個異步請求。

requestStream.subscribe(function(requestUrl) {
  // execute the request
  var responseStream = Rx.Observable.create(function (observer) {
    jQuery.getJSON(requestUrl)
    .done(function(response) { observer.onNext(response); })
    .fail(function(jqXHR, status, error) { observer.onError(error); })
    .always(function() { observer.onCompleted(); });
  });

  responseStream.subscribe(function(response) {
    // do something with the response
  });
}

Rx.Observable.create()用於創建專屬定製流,通過把數據事件傳通告給各個觀察者,或者訂閱者。
Promise 也是一個觀察者,只不過接收一個參數。
Rx流卻可以處理很多。

map(f) 從流a提取數據,實施函數f,然後產生流b。會產生流中流,分流。
本例中,返回流如果用map,會產生新的流(流走了,收不到?)。同時請求和返回都是以promise單獨存在。

這裏寫圖片描述
我們需要讓map不產生新的流,以便能夠接受。
所以用flatMap,扁平版map,不會產生流b
這裏寫圖片描述

requestStream:  --a-----b--c------------|->
responseStream: -----A--------B-----C---|->

收到response流後,就可以渲染了。

刷新

做一個刷新點擊流(刷新按鈕),同時請求流需要依靠刷新點擊流。
RxJS內置對應工具

var refreshButton = document.querySelector('.refresh');
var refreshClickStream = Rx.Observable.fromEvent(refreshButton, 'click');

刷新事件流本身不帶有api url,需要給予對url通過map。
把請求流連接刷新流

var requestOnRefreshStream = refreshClickStream
  .map(function() {
    var randomOffset = Math.floor(Math.random()*500);
    return 'https://api.github.com/users?since=' + randomOffset;
  });

var startupRequestStream = Rx.Observable.just('https://api.github.com/users');

合併兩個流

stream A: ---a--------e-----o----->
stream B: -----B---C-----D-------->
          vvvvvvvvv merge vvvvvvvvv
          ---a-B---C--e--D--o----->

modeling 3 suggestion

每一個建議當成流,

整體流程如下

refreshClickStream: ----------o--------o---->
     requestStream: -r--------r--------r---->
    responseStream: ----R---------R------R-->   
 suggestion1Stream: ----s-----N---s----N-s-->
 suggestion2Stream: ----q-----N---q----N-q-->
 suggestion3Stream: ----t-----N---t----N-t-->

n爲null
或者設置在啓動時數據默認爲n

refreshClickStream: ----------o---------o---->
     requestStream: -r--------r---------r---->
    responseStream: ----R----------R------R-->   
 suggestion1Stream: -N--s-----N----s----N-s-->
 suggestion2Stream: -N--q-----N----q----N-q-->
 suggestion3Stream: -N--t-----N----t----N-t-->

關閉 出現

關閉一個建議,加載一個新的。

requestStream: --r--------------->
   responseStream: ------R----------->
close1ClickStream: ------------c----->
suggestion1Stream: ------s-----s----->

Rx*有函數combineLatest可以綁定兩個流最近的 如圖:

stream A: --a-----------e--------i-------->
stream B: -----b----c--------d-------q---->
          vvvvvvvv combineLatest(f) vvvvvvv
          ----AB---AC--EC---ED--ID--IQ---->

可以用來綁定close1ClickStreamsuggestion1Stream

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章