国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

通俗的方式理解RxJS

jzzlee / 558人閱讀

摘要:到底是什么先上代碼輸出這里可以把想象成一個(gè)函數(shù),這意味著你每次調(diào)用都會(huì)導(dǎo)致傳入里的回調(diào)函數(shù)重新執(zhí)行一次調(diào)用的方式為相當(dāng)于。接收函數(shù)返回值的方式也從改為通過傳入回調(diào)函數(shù)的方式獲取。具體看代碼運(yùn)行結(jié)果如上的第一個(gè)回調(diào)函數(shù)里的結(jié)構(gòu)是推薦的結(jié)構(gòu)。

通俗的方式理解Rx.js 序言

今早看民工叔的文章的時(shí)候, 發(fā)現(xiàn)對(duì)Rxjs所知甚少, 于是去官方看了下教程, 整理出一些東西, 寫成此文。
Rxjs據(jù)說會(huì)在2017年流行起來, 因?yàn)槠涮幚懋惒竭壿嫞瑪?shù)據(jù)流, 事件非常擅長(zhǎng)。 但是其學(xué)習(xí)曲線相比Promise, EventEmitter陡峭了不少。 而且民工叔也說:"由于RxJS的抽象程度很高,所以,可以用很簡(jiǎn)短代碼表達(dá)很復(fù)雜的含義,這對(duì)開發(fā)人員的要求也會(huì)比較高,需要有比較強(qiáng)的歸納能力。" 本文就Rx.js的幾個(gè)核心概念做出闡述。 盡可能以通俗易懂的方式解釋這些概念。要是本文有誤或不完善的地方,歡迎指出。

Observable到底是什么

先上代碼:

let foo = Rx.Observable.create(observer => {
  console.log("Hello");
  observer.next(42);
});

foo.subscribe(x => console.log(x));
foo.subscribe(y => console.log(y));

輸出

"Hello"
42
"Hello"
42

這里可以把foo想象成一個(gè)函數(shù),這意味著你每次調(diào)用foo都會(huì)導(dǎo)致傳入Rx.Observable.create里的回調(diào)函數(shù)重新執(zhí)行一次, 調(diào)用的方式為foo.subscribe(callback), 相當(dāng)于foo()。 接收函數(shù)返回值的方式也從var a = foo()改為通過傳入回調(diào)函數(shù)的方式獲取。第三行的observer.next表示返回一個(gè)值, 你可以調(diào)用多次,每次調(diào)用observer.next后, 會(huì)先將next里的值返回給foo.subcribe里的回調(diào)函數(shù), 執(zhí)行完后再返回。observer.complete, observer.error來控制流程。 具體看代碼:

var observable = Rx.Observable.create(observer => {
  try {
    observer.next(1);
    console.log("hello");
    observer.next(2);
    observer.next(3);
    observer.complete();
    observer.next(4);
  } catch (err) {
    observer.error(err); 
  }
});

let = subcription = observable.subscribe(value => {
  console.log(value)
})

運(yùn)行結(jié)果:

1
hello
2
3

如上的第一個(gè)回調(diào)函數(shù)里的結(jié)構(gòu)是推薦的結(jié)構(gòu)。 當(dāng)observable的執(zhí)行出現(xiàn)異常的時(shí)候,通過observer.error將錯(cuò)誤返回, 然而observable.subscribe的回調(diào)函數(shù)無法接收到.因?yàn)閛bserver.complete已經(jīng)調(diào)用, 因此observer.next(4)的返回是無效的. Observable不是可以返回多個(gè)值的Promise 雖然獲得Promise的值的方式也是通過then函數(shù)這種類似的方式, 但是new Promise(callback)里的callback回調(diào)永遠(yuǎn)只會(huì)執(zhí)行一次!因?yàn)?strong>Promise的狀態(tài)是不可逆的。

可以使用其他方式創(chuàng)建Observable, 看代碼:

var clicks = Rx.Observable.fromEvent(document, "click");
clicks.subscribe(x => console.log(x));

當(dāng)用戶對(duì)document產(chǎn)生一個(gè)click行為的時(shí)候, 就會(huì)打印事件對(duì)象到控制臺(tái)上。

Observer是什么

先看代碼:

let foo = Rx.Observable.create(observer => {
  console.log("Hello");
  observer.next(42);
});

let observer = x => console.log(x);
foo.subscribe(observer);

代碼中的第二個(gè)變量就是observer. 沒錯(cuò), observer就是當(dāng)Observable"返回"值的時(shí)候接受那個(gè)值的函數(shù)!第一行中的observer其實(shí)就是通過foo.subscribe傳入的callback. 只不過稍加封裝了。 怎么封裝的? 看代碼:

let foo = Rx.Observable.create(observer => {
  try {
    console.log("Hello");
    observer.next(42);
    observer.complete();
    observer.next(10);
  } catch(e) { observer.error(e) }
  
});

let observer = {
  next(value) { console.log(value) },
  complete() { console.log("completed"),
  error(err) { console.error(err) }
}
foo.subscribe(observer);

你看到observer被定義成了一個(gè)對(duì)象, 其實(shí)這才是完整的observer. 傳入一個(gè)callback到observable.subcribe相當(dāng)于傳入了{ next: callback }

Subcription里的陷阱

Subscription是什么, 先上代碼:

var observable = Rx.Observable.interval(1000);
var subscription = observable.subscribe(x => console.log(x));

setTimeout(() => {
  subscription.unsubscribe();
}, 3100)

運(yùn)行結(jié)果:

0
1
2

Rx.Observable.interval可以返回一個(gè)能夠發(fā)射(返回)0, 1, 2, 3..., n數(shù)字的Observable, 返回的時(shí)間間隔這里是1000ms。 第二行中的變量就是subscription。 subscription有一個(gè)unsubscribe方法, 這個(gè)方法可以讓subscription訂閱的observable發(fā)射的數(shù)據(jù)被observer忽略掉.通俗點(diǎn)說就是取消訂閱。

unsubscribe存在一個(gè)陷阱。 先看代碼:

var foo = Rx.Observable.create((observer) => {
  var i = 0
  setInterval(() => {
    observer.next(i++)
    console.log("hello")
  }, 1000)
})

const subcription = foo.subscribe((i) => console.log(i))
subcription.unsubscribe()

運(yùn)行結(jié)果:

hello
hello
hello
......
hello

unsubscribe只會(huì)讓observer忽略掉observable發(fā)射的數(shù)據(jù),但是setInterval依然會(huì)繼續(xù)執(zhí)行。 這看起來似乎是一個(gè)愚蠢的設(shè)計(jì)。 所以不建議這樣寫。

Subject

Subject是一種能夠發(fā)射數(shù)據(jù)給多個(gè)observer的Observable, 這讓Subject看起來就好像是EventEmitter。 先上代碼:

var subject = new Rx.Subject();

subject.subscribe({
  next: (v) => console.log("observerA: " + v)
});
subject.subscribe({
  next: (v) => console.log("observerB: " + v)
});

subject.next(1);
subject.next(2);

運(yùn)行結(jié)果:

observerA: 1
observerB: 1
observerA: 2
observerB: 2

與Observable不同的是, Subject發(fā)射數(shù)據(jù)給多個(gè)observer。 其次, 定義subject的時(shí)候并沒有傳入callback, 這是因?yàn)閟ubject自帶next, complete, error等方法。從而可以發(fā)射數(shù)據(jù)給observer。 這和EventEmitter很類似。observer并不知道他subscribe的是Obervable還是Subject。 對(duì)observer來說是透明的。 而且Subject還有各種派生, 比如說:

BehaviorSubject 能夠保留最近的數(shù)據(jù),使得當(dāng)有subscribe的時(shí)候,立馬發(fā)射出去。看代碼:

var subject = new Rx.BehaviorSubject(0); // 0 is the initial value

subject.subscribe({
  next: (v) => console.log("observerA: " + v)
});

subject.next(1);
subject.next(2);

subject.subscribe({
  next: (v) => console.log("observerB: " + v)
});

subject.next(3);

運(yùn)行結(jié)果:

observerA: 0
observerA: 1
observerA: 2
observerB: 2
observerA: 3
observerB: 3

ReplaySubject 能夠保留最近的一些數(shù)據(jù), 使得當(dāng)有subscribe的時(shí)候,將這些數(shù)據(jù)發(fā)射出去。看代碼:

var subject = new Rx.ReplaySubject(3); 

subject.subscribe({
  next: (v) => console.log("observerA: " + v)
});

subject.next(1);
subject.next(2);
subject.next(3);
subject.next(4);

subject.subscribe({
  next: (v) => console.log("observerB: " + v)
});

subject.next(5);

輸出結(jié)果:

observerA: 1
observerA: 2
observerA: 3
observerA: 4
observerB: 2
observerB: 3
observerB: 4
observerA: 5
observerB: 5

第一行的聲明表示ReplaySubject最大能夠記錄的數(shù)據(jù)的數(shù)量是3。

AsyncSubject 只會(huì)發(fā)射結(jié)束前的一個(gè)數(shù)據(jù)。 看代碼:

var subject = new Rx.AsyncSubject();

subject.subscribe({
  next: (v) => console.log("observerA: " + v)
});

subject.next(1);
subject.next(2);
subject.next(3);
subject.next(4);

subject.subscribe({
  next: (v) => console.log("observerB: " + v)
});

subject.next(5);
subject.complete();

輸出結(jié)果:

observerA: 5
observerB: 5

既然subject有next, error, complete三種方法, 那subject就可以作為observer! 看代碼:

var subject = new Rx.Subject();

subject.subscribe({
  next: (v) => console.log("observerA: " + v)
});
subject.subscribe({
  next: (v) => console.log("observerB: " + v)
});

var observable = Rx.Observable.from([1, 2, 3]);

observable.subscribe(subject);

輸出結(jié)果:

observerA: 1
observerB: 1
observerA: 2
observerB: 2
observerA: 3
observerB: 3

也就是說, observable.subscribe可以傳入一個(gè)subject來訂閱其消息。 這就好像是Rxjs中的一顆語法糖, Rxjs有專門的實(shí)現(xiàn)。

Multicasted Observables 是一種借助Subject來將數(shù)據(jù)發(fā)射給多個(gè)observer的Observable。 看代碼:

var source = Rx.Observable.from([1, 2, 3]);
var subject = new Rx.Subject();
var multicasted = source.multicast(subject);

multicasted.subscribe({
  next: (v) => console.log("observerA: " + v)
});
multicasted.subscribe({
  next: (v) => console.log("observerB: " + v)
});

multicasted.connect();

Rx.Observable.from能夠逐一發(fā)射數(shù)組中的元素, 在multicasted.connect()調(diào)用之前的任何subscribe都不會(huì)導(dǎo)致source發(fā)射數(shù)據(jù)。multicasted.connect()相當(dāng)于之前的observable.subscribe(subject)。因此不能將multicasted.connect()寫在subscribe的前面。因?yàn)檫@會(huì)導(dǎo)致在執(zhí)行multicasted.connect()的時(shí)候source發(fā)射數(shù)據(jù), 但是subject又沒保存數(shù)據(jù), 導(dǎo)致兩個(gè)subscribe無法接收到任何數(shù)據(jù)。

最好是第一個(gè)subscribe的時(shí)候能夠得到當(dāng)前已有的數(shù)據(jù), 最后一個(gè)unsubscribe的時(shí)候就停止Observable的執(zhí)行, 相當(dāng)于Observable發(fā)射的數(shù)據(jù)都被忽略。

refCount就是能夠返回這樣的Observable的方法

var source = Rx.Observable.interval(500);
var subject = new Rx.Subject();
var refCounted = source.multicast(subject).refCount();
var subscription1, subscription2, subscriptionConnect;

console.log("observerA subscribed");
subscription1 = refCounted.subscribe({
  next: (v) => console.log("observerA: " + v)
});

setTimeout(() => {
  console.log("observerB subscribed");
  subscription2 = refCounted.subscribe({
    next: (v) => console.log("observerB: " + v)
  });
}, 600);

setTimeout(() => {
  console.log("observerA unsubscribed");
  subscription1.unsubscribe();
}, 1200);

setTimeout(() => {
  console.log("observerB unsubscribed");
  subscription2.unsubscribe();
}, 2000);

輸出結(jié)果:

observerA subscribed
observerA: 0
observerB subscribed
observerA: 1
observerB: 1
observerA unsubscribed
observerB: 2
observerB unsubscribed
What"s Operators?

Observable上有很多方法, 比如說map, filter, merge等等。 他們基于調(diào)用它們的observable,返回一個(gè)全新的observable。 而且他們都是純方法。 operators分為兩種, instance operators 和 static operators。 instance operators是存在于observable實(shí)例上的方法, 也就是實(shí)例方法; static operators是存在于Observable這個(gè)類型上的方法, 也就是靜態(tài)方法。Rxjs擁有很多強(qiáng)大的operators。

自己實(shí)現(xiàn)一個(gè)operators:

function multiplyByTen(input) {
  var output = Rx.Observable.create(function subscribe(observer) {
    input.subscribe({
      next: (v) => observer.next(10 * v),
      error: (err) => observer.error(err),
      complete: () => observer.complete()
    });
  });
  return output;
}

var input = Rx.Observable.from([1, 2, 3, 4]);
var output = multiplyByTen(input);
output.subscribe(x => console.log(x));

輸出結(jié)果:

10
20
30
40
Rx.js實(shí)踐
import React from "react";
import ReactDOM from "react-dom";
import Rx from "rx";

class Main extends React.Component {
  constructor (props) {
    super(props);
    this.state = {count: 0};
  }

  // Click events are now observables! No more proactive approach.
  componentDidMount () {
    const plusBtn = document.getElementById("plus");
    const minusBtn = document.getElementById("minus");

    const plus$ = Rx.Observable.fromEvent(plusBtn, "click").map(e => 1);
    const minus$ = Rx.Observable.fromEvent(minusBtn, "click").map(e => -1);

    Rx.Observable.merge(plus$, minus$).scan((acc, n) => acc + n)
      .subscribe(value => this.setState({count: value}));
  }

  render () {
    return (
        
count: {this.state.count}
); } } ReactDOM.render(
, document.getElementById("app"));

merge用于合并兩個(gè)observable產(chǎn)生一個(gè)新的observable。 scan類似于Array中的reduce。 這個(gè)例子實(shí)現(xiàn)了點(diǎn)擊plus的時(shí)候+1, 點(diǎn)擊minus的時(shí)候-1。

Rx.js適用的場(chǎng)景

多個(gè)復(fù)雜的異步或事件組合在一起。

處理多個(gè)數(shù)據(jù)序列

假如沒有被復(fù)雜的異步,事件, 數(shù)據(jù)序列困擾, 如果promise已經(jīng)足夠的話, 就沒必要適用Rx.js。

Summary

Observable, Observer, Subscription, Subscrib, Subject概念。

RxJS適用于解決復(fù)雜的異步,事件問題。

文章參考

讓我們一起來學(xué)習(xí) RxJS ---by 餓了么前端

21-use-rxjs-for-orchestrating-asynchronous-and-event-based-computations

RxJS文檔

RxJS 入門指引和初步應(yīng)用 ---by 民工叔

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/81707.html

相關(guān)文章

  • 2018前端值得關(guān)注技術(shù)

    摘要:年前端有哪些領(lǐng)域,技術(shù)值得關(guān)注,哪些技術(shù)會(huì)興起,哪些技術(shù)會(huì)沒落。自從谷歌提出后,就持續(xù)的獲得了業(yè)界的關(guān)注,熱度可見一斑。就在今年,谷歌也宣布將獲得與安卓原生應(yīng)用同等的待遇與權(quán)限。但是無論都值得關(guān)注。 1.前言 2017悄然過去,2018已經(jīng)來到。人在進(jìn)步,技術(shù)在發(fā)展。2018年前端有哪些領(lǐng)域,技術(shù)值得關(guān)注,哪些技術(shù)會(huì)興起,哪些技術(shù)會(huì)沒落。下面就我個(gè)人的判斷進(jìn)行一個(gè)預(yù)測(cè)判斷,希望能對(duì)大家...

    xiao7cn 評(píng)論0 收藏0
  • 2018前端值得關(guān)注技術(shù)

    摘要:年前端有哪些領(lǐng)域,技術(shù)值得關(guān)注,哪些技術(shù)會(huì)興起,哪些技術(shù)會(huì)沒落。自從谷歌提出后,就持續(xù)的獲得了業(yè)界的關(guān)注,熱度可見一斑。就在今年,谷歌也宣布將獲得與安卓原生應(yīng)用同等的待遇與權(quán)限。但是無論都值得關(guān)注。 1.前言 2017悄然過去,2018已經(jīng)來到。人在進(jìn)步,技術(shù)在發(fā)展。2018年前端有哪些領(lǐng)域,技術(shù)值得關(guān)注,哪些技術(shù)會(huì)興起,哪些技術(shù)會(huì)沒落。下面就我個(gè)人的判斷進(jìn)行一個(gè)預(yù)測(cè)判斷,希望能對(duì)大家...

    用戶84 評(píng)論0 收藏0
  • 【響應(yīng)式編程思維藝術(shù)】 (1)Rxjs專題學(xué)習(xí)計(jì)劃

    摘要:由于技術(shù)棧的學(xué)習(xí),筆者需要在原來函數(shù)式編程知識(shí)的基礎(chǔ)上,學(xué)習(xí)的使用。筆者在社區(qū)發(fā)現(xiàn)了一個(gè)非常高質(zhì)量的響應(yīng)式編程系列教程共篇,從基礎(chǔ)概念到實(shí)際應(yīng)用講解的非常詳細(xì),有大量直觀的大理石圖來輔助理解流的處理,對(duì)培養(yǎng)響應(yīng)式編程的思維方式有很大幫助。 showImg(https://segmentfault.com/img/bVus8n); [TOC] 一. 響應(yīng)式編程 響應(yīng)式編程,也稱為流式編程...

    lscho 評(píng)論0 收藏0
  • 【CuteJavaScript】Angular6入門項(xiàng)目(3.編寫服務(wù)和引入RxJS

    摘要:發(fā)布通過回調(diào)方法向發(fā)布事件。觀察者一個(gè)回調(diào)函數(shù)的集合,它知道如何去監(jiān)聽由提供的值。 本文目錄 一、項(xiàng)目起步 二、編寫路由組件 三、編寫頁面組件 1.編寫單一組件 2.模擬數(shù)據(jù) 3.編寫主從組件 四、編寫服務(wù) 1.為什么需要服務(wù) 2.編寫服務(wù) 五、引入RxJS 1.關(guān)于RxJS 2.引入RxJS 3.改造數(shù)據(jù)獲取方式 六、改造組件 1.添...

    RebeccaZhong 評(píng)論0 收藏0
  • RxJS Observable - 一個(gè)奇特函數(shù)

    摘要:形式上比普通函數(shù)直接返回值啰嗦一些。這里和的重要區(qū)別在于,模式下,可以決定什么時(shí)候返回值,以及返回幾個(gè)值即調(diào)用回調(diào)函數(shù)的次數(shù)。 前言 RxJS 的 Observable 有點(diǎn)難理解,其實(shí) RxJS 相關(guān)的概念都有點(diǎn)難理解。畢竟 RxJS 引入了響應(yīng)式編程這種新的模式,會(huì)不習(xí)慣是正常的。不過總得去理解嘛,而認(rèn)識(shí)新的事物時(shí),如果能夠參照一個(gè)合適的已知事物比對(duì)著,會(huì)比較容易理解吧。對(duì)于 Ob...

    omgdog 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<