亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

RxJs 核心概念之Observable

forrest23 / 663人閱讀

摘要:函數(shù)調(diào)用后同步計(jì)算并返回單一值生成器函數(shù)遍歷器遍歷過(guò)程中同步計(jì)算并返回個(gè)到無(wú)窮多個(gè)值異步執(zhí)行中返回或者不返回單一值同步或者異步計(jì)算并返回個(gè)到無(wú)窮多個(gè)值是函數(shù)概念的拓展既不像,也不像是。如果不調(diào)用函數(shù),就不會(huì)執(zhí)行如果如果不訂閱,也不會(huì)執(zhí)行。

Observable(可觀察對(duì)象)是基于推送(Push)運(yùn)行時(shí)執(zhí)行(lazy)的多值集合。下方表格對(duì)Observable進(jìn)行了定位(為解決基于推送的多值問(wèn)題):

MagicQ 單值 多值
拉取(Pull) 函數(shù) 遍歷器
推送(Push) Promise Observable

:當(dāng)observable被訂閱后,會(huì)立即(同步地)推送1, 2, 3 三個(gè)值;1秒之后,繼續(xù)推送4這個(gè)值,最后結(jié)束(推送結(jié)束通知):

var observable = Rx.Observable.create(function (observer) {
  observer.next(1);
  observer.next(2);
  observer.next(3);
  setTimeout(() => {
    observer.next(4);
    observer.complete();
  }, 1000);
});

為得到observable推送的值,我們需要訂閱(subscribe)這個(gè)Observable:

var observable = Rx.Observable.create(function (observer) {
  observer.next(1);
  observer.next(2);
  observer.next(3);
  setTimeout(() => {
    observer.next(4);
    observer.complete();
  }, 1000);
});

console.log("just before subscribe");
observable.subscribe({
  next: x => console.log("got value " + x),
  error: err => console.error("something wrong occurred: " + err),
  complete: () => console.log("done"),
});
console.log("just after subscribe");

程序執(zhí)行后,將在控制臺(tái)輸出如下結(jié)果:

just before subscribe
got value 1
got value 2
got value 3
just after subscribe
got value 4
done
拉取(Pull) V.S. 推送(Push)

拉取推送是數(shù)據(jù)生產(chǎn)者和數(shù)據(jù)消費(fèi)者之間通信的兩種不同機(jī)制。

何為拉取? 在拉取系統(tǒng)中,總是由消費(fèi)者決定何時(shí)從生產(chǎn)者那里獲得數(shù)據(jù)。生產(chǎn)者對(duì)數(shù)據(jù)傳遞給消費(fèi)者的時(shí)間毫無(wú)感知(被動(dòng)的生產(chǎn)者,主動(dòng)的消費(fèi)者)。

JavaScript函數(shù)是典型的拉取系統(tǒng):函數(shù)是數(shù)據(jù)的生產(chǎn)者,對(duì)函數(shù)進(jìn)行調(diào)用的代碼(消費(fèi)者)從函數(shù)調(diào)用后的返回值中拉取單值進(jìn)行消費(fèi)。

// 函數(shù)是數(shù)據(jù)的生產(chǎn)者
let getLuckyNumber = function() {
    return 7;
};

/* let代碼段是數(shù)據(jù)的消費(fèi)者,
 * getLuckyNumber對(duì)調(diào)用時(shí)間毫無(wú)感知。 
 */
let luckNumber = getLuckyNumber();

ES2015 引入了的 生成器函數(shù) | 遍歷器 (function*)同樣是基于拉取的系統(tǒng): 調(diào)用 iterator.next()的代碼段是消費(fèi)者,它可以從生成器函數(shù)中拉取多個(gè)值。

function* getLessThanTen() {
  var i = 0;
  while(i < 11) {
    yield i++;
  }
}

// 生產(chǎn)者
let iterator = getLessThanTen();

// 消費(fèi)者
iterator.next(); // Object {value: 0, done: false}
iterator.next(); // Object {value: 1, done: false}
MagicQ 生產(chǎn)者 消費(fèi)者
拉取 被動(dòng): 在被請(qǐng)求時(shí)產(chǎn)生數(shù)據(jù) 主動(dòng): 決定何時(shí)請(qǐng)求數(shù)據(jù)
推送 主動(dòng): 控制數(shù)據(jù)的產(chǎn)生邏輯 被動(dòng): 獲得數(shù)據(jù)后進(jìn)行響應(yīng)

何為推送? 在推送系統(tǒng)中生產(chǎn)者決定何時(shí)向消費(fèi)者傳遞數(shù)據(jù),消費(fèi)者對(duì)何時(shí)收到數(shù)據(jù)毫無(wú)感知(被動(dòng)的消費(fèi)者)。

現(xiàn)代JavaScript中Promise是典型的推送系統(tǒng)。作為數(shù)據(jù)生產(chǎn)者的Promise通過(guò)resolve()向數(shù)據(jù)消費(fèi)者——回調(diào)函數(shù)傳遞數(shù)據(jù):與函數(shù)不同,Promise決定向回調(diào)函數(shù)推送值的時(shí)間。

RxJS在 JavaScript 中引入了Observable(可觀察對(duì)象)這個(gè)新的推送系統(tǒng)。Observable是多數(shù)據(jù)值的生產(chǎn)者,向Observer(被動(dòng)的消費(fèi)者)推送數(shù)據(jù)。

函數(shù) 調(diào)用后同步計(jì)算并返回單一值

生成器函數(shù) | 遍歷器 遍歷過(guò)程中同步計(jì)算并返回0個(gè)到無(wú)窮多個(gè)值

Promise 異步執(zhí)行中返回或者不返回單一值

Observable 同步或者異步計(jì)算并返回0個(gè)到無(wú)窮多個(gè)值

Observable 是函數(shù)概念的拓展

Observable既不像EventEmitter,也不像是Promise。Observable 中的 Subject 進(jìn)行多路推送時(shí)與 EventEmitter 行為上有些類(lèi)似,但是實(shí)際上Observable與EventEmitter并不相同。

Observable 更像是一個(gè)不需要傳入?yún)?shù)的函數(shù),它拓展了函數(shù)的概念使得它可以返回多個(gè)值。

看看下面的例子:

function foo() {
  console.log("Hello");
  return 42;
}

var x = foo.call(); // same as foo()
console.log(x);
var y = foo.call(); // same as foo()
console.log(y);

輸出結(jié)果如下:

"Hello"
42
"Hello"
42

通過(guò)Observable可以實(shí)現(xiàn)同樣的行為:

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

foo.subscribe(function (x) {
  console.log(x);
});
foo.subscribe(function (y) {
  console.log(y);
});

輸出結(jié)果相同:

"Hello"
42
"Hello"
42

不論Observable還是函數(shù)都是在運(yùn)行時(shí)進(jìn)行求值計(jì)算的。如果不調(diào)用函數(shù),console.log("Hello")就不會(huì)執(zhí)行;如果如果不subscribe(訂閱)Observable,console.log("Hello")也不會(huì)執(zhí)行。此外,調(diào)用或者訂閱都是獨(dú)立的:兩次調(diào)用產(chǎn)生兩個(gè)獨(dú)立的作用域,兩次訂閱同樣會(huì)產(chǎn)生兩個(gè)獨(dú)立的作用域。EventEmitter總是在同一個(gè)作用域中,發(fā)射前也不會(huì)在意自己是否已經(jīng)被訂閱;Observable不會(huì)被共享而產(chǎn)生副作用,并且總是在被訂閱時(shí)才執(zhí)行。

訂閱Observable與調(diào)用函數(shù)類(lèi)似。

一些人認(rèn)為Observable總是是異步的,這個(gè)觀點(diǎn)并不正確,如果在控制臺(tái)log函數(shù)中調(diào)用函數(shù):

console.log("before");
console.log(foo.call());
console.log("after");

顯然可以看到以下輸出:

"before"
"Hello"
42
"after"

Observable的行為完全一樣:

console.log("before");
foo.subscribe(function (x) {
  console.log(x);
});
console.log("after");

輸出結(jié)果為:

"before"
"Hello"
42
"after"

訂閱 foo完全是同步的,與函數(shù)的調(diào)用一樣。

Observable可以異步或者同步地產(chǎn)生數(shù)據(jù)。

那Observable 與函數(shù)的不同之處在哪里? Observable可以在一個(gè)時(shí)間過(guò)程中‘返回’多個(gè)值,而函數(shù)卻不能。在函數(shù)中你不可以這么做:

function foo() {
  console.log("Hello");
  return 42;
  return 100; // 這個(gè)語(yǔ)句永遠(yuǎn)不會(huì)被執(zhí)行。
}

雖然函數(shù)只能有一個(gè)返回值,但是在Observable中你完全可以這么做:

var foo = Rx.Observable.create(function (observer) {
  console.log("Hello");
  observer.next(42);
  observer.next(100); // 返回另一個(gè)值
  observer.next(200); // 返回另一個(gè)值
});

console.log("before");
foo.subscribe(function (x) {
  console.log(x);
});
console.log("after");

輸出結(jié)果如下:

"before"
"Hello"
42
100
200
"after"

你甚至可以異步地返回值:

var foo = Rx.Observable.create(function (observer) {
  console.log("Hello");
  observer.next(42);
  observer.next(100);
  observer.next(200);
  setTimeout(() => {
    observer.next(300); // happens asynchronously
  }, 1000);
});

console.log("before");
foo.subscribe(function (x) {
  console.log(x);
});
console.log("after");

輸出結(jié)果:

"before"
"Hello"
42
100
200
"after"
300

結(jié)論:

func.call() 意味著“同步地給我一個(gè)值”

observable.subscribe() 意味著“不管是同步或者異步,給我一些值”

Observable 剖析

通過(guò)使用 Rx.Observable.create 或者是創(chuàng)建操作符,創(chuàng)建一個(gè)Observable; Observable 被 Observer(觀察者) 訂閱; 在執(zhí)行時(shí) 向觀察者發(fā)送next / error / complete 通知;同時(shí)執(zhí)行過(guò)程可以被 終止。
Observable 類(lèi)型的實(shí)例具備了以上四個(gè)方面的特性,與其他類(lèi)型如:Observer 和 Subscription 緊密相關(guān)。

我們重點(diǎn)關(guān)注以下四個(gè)方面:

創(chuàng)建

訂閱

執(zhí)行

終止

創(chuàng)建

Rx.Observable.createObservable 構(gòu)造函數(shù)的別名,接受一個(gè)參數(shù): subscribe函數(shù)。

以下例子會(huì)創(chuàng)建一個(gè)Observable,每一秒鐘向其訂閱者發(fā)射一個(gè)"hi" 字符串。

var observable = Rx.Observable.create(function subscribe(observer) {
  var id = setInterval(() => {
    observer.next("hi")
  }, 1000);
});

除了使用create創(chuàng)建Observable,我們通常還使用創(chuàng)建操作符, 如 of,from, interval, 等來(lái)創(chuàng)建Observable。

上面例子中,subscribe函數(shù)是定義Observable最重要的部分。我們接下來(lái)了解訂閱的含義。

訂閱

上面例子中的observable 可以以如下方式 訂閱

observable.subscribe(x => console.log(x));

observable.subscribeObservable.create(function subscribe(observer) {...})中的subscribe 同名并非巧合。雖然在Rx中它們不是同一個(gè)對(duì)象,但是在工程中,我們可以在概念上視兩者為等價(jià)物。

調(diào)用subscribe的觀察者并不會(huì)共享同一個(gè)Observable。觀察者調(diào)用observable.subscribe 時(shí),Observable.create(function subscribe(observer) {...})中的subscribe會(huì)在調(diào)用它的觀察者作用域中執(zhí)行。每一次observable.subscribe的調(diào)用,都是彼此獨(dú)立的。

訂閱Observable如同調(diào)用函數(shù),需要提供相應(yīng)的回調(diào)方法。

訂閱機(jī)制與處理事件的addEventListener / removeEventListenerAPI完全不同。通過(guò)observable.subscribe,觀察者并不需要在Observable中進(jìn)行注冊(cè),Observable也不需要維護(hù)訂閱者的列表。

訂閱后便進(jìn)入了Observable的執(zhí)行階段,在執(zhí)行階段值和事件將會(huì)被傳遞給觀察者供其消費(fèi)。

執(zhí)行

只有在被訂閱之后Observable才會(huì)執(zhí)行,執(zhí)行的邏輯在Observable.create(function subscribe(observer) {...})中描述,執(zhí)行后將會(huì)在特定時(shí)間段內(nèi),同步或者異步地成產(chǎn)多個(gè)數(shù)據(jù)值。

Observable在執(zhí)行過(guò)程中,可以推送三種類(lèi)型的值:

"Next" 通知: 實(shí)際產(chǎn)生的數(shù)據(jù),包括數(shù)字、字符串、對(duì)象等

"Error" 通知:一個(gè)JavaScript錯(cuò)誤或者異常

"Complete" 通知:一個(gè)不帶有值的事件

“Next” 通知是最重要和常用的類(lèi)型:表示事件傳遞給觀察者的數(shù)據(jù)。錯(cuò)誤和完成通知僅會(huì)在執(zhí)行階段推送其一,并不會(huì)同時(shí)推送錯(cuò)誤和完成通知。

通過(guò)所謂的“Observable語(yǔ)法”或者“契約”可以最好地表達(dá)這個(gè)規(guī)則,“Observable語(yǔ)法”借助于正則表達(dá)式:

next*(error|complete)?

在Observable的執(zhí)行過(guò)程中,0個(gè)或者多個(gè)“Next”通知會(huì)被推送。在錯(cuò)誤或者完成通知被推送后,Observable不會(huì)再推送任何其他通知。

下面代碼展示了Observable 在執(zhí)行過(guò)程中推送3個(gè)“Next” 通知然后結(jié)束:

var observable = Rx.Observable.create(function subscribe(observer) {
  observer.next(1);
  observer.next(2);
  observer.next(3);
  observer.complete();
});

Observable 嚴(yán)格遵守 Observable 契約,后面值為4的“Next” 通知永遠(yuǎn)不會(huì)被推送:

var observable = Rx.Observable.create(function subscribe(observer) {
  observer.next(1);
  observer.next(2);
  observer.next(3);
  observer.complete();
  observer.next(4); // 由于違法契約,4不會(huì)被推送
});

使用try/catch塊包裹 subscribe 代碼是一個(gè)很贊的想法,如果捕獲了異常,可以推送錯(cuò)誤通知:

var observable = Rx.Observable.create(function subscribe(observer) {
  try {
    observer.next(1);
    observer.next(2);
    observer.next(3);
    observer.complete();
  } catch (err) {
    observer.error(err); // 捕獲異常后推送錯(cuò)誤通知
  }
});
終止

Observable的執(zhí)行可能是無(wú)限的,作為觀察者需要主動(dòng)中斷執(zhí)行:我們需要特定的API去終止執(zhí)行過(guò)程。因?yàn)樘囟ǖ挠^察者都有特定的執(zhí)行過(guò)程,一旦觀察者獲得想要的數(shù)據(jù)后就需要終止執(zhí)行過(guò)程以免帶來(lái)計(jì)算時(shí)對(duì)內(nèi)存資源的浪費(fèi)。

observable.subscribe被調(diào)用時(shí),觀察者會(huì)與其執(zhí)行作用域綁定,同時(shí)返回一個(gè)Subscription類(lèi)型的對(duì)象:

var subscription = observable.subscribe(x => console.log(x));

Subscription對(duì)象表示執(zhí)行過(guò)程,通過(guò)極簡(jiǎn)的API,你可以終止執(zhí)行過(guò)程。詳情請(qǐng)閱讀Subscription 相關(guān)文檔。通過(guò)調(diào)用subscription.unsubscribe() 你可以終止執(zhí)行過(guò)程:

var observable = Rx.Observable.from([10, 20, 30]);
var subscription = observable.subscribe(x => console.log(x));
// Later:
subscription.unsubscribe();

在Observable被訂閱后,代表執(zhí)行過(guò)程的Subscription 對(duì)象將被返回。對(duì)其調(diào)用unsubscribe()就可以終止執(zhí)行。

每一個(gè)Observable都需要在 create()的創(chuàng)建過(guò)程中定義終止的邏輯。在function subscribe()中返回自定義的unsubscribe就可以實(shí)現(xiàn)。

下面的例子說(shuō)明了如何在終止后釋放setInterval的句柄:

var observable = Rx.Observable.create(function subscribe(observer) {
  // 獲得定時(shí)函數(shù)的句柄
  var intervalID = setInterval(() => {
    observer.next("hi");
  }, 1000);
  
  // 提供終止方法釋放定時(shí)函數(shù)的句柄
  return function unsubscribe() {
    clearInterval(intervalID);
  };
});

類(lèi)似于observable.subscribeObservable.create(function subscribe() {...})的關(guān)系,我們?cè)?b>subscribe中返回的 unsubscribe 也與subscription.unsubscribe在概念上等價(jià)。事實(shí)上,如果我們除去Rx的包裝,純粹的JavaScript代碼簡(jiǎn)單清晰:

function subscribe(observer) {
  var intervalID = setInterval(() => {
    observer.next("hi");
  }, 1000);
  
  return function unsubscribe() {
    clearInterval(intervalID);
  };
}

var unsubscribe = subscribe({next: (x) => console.log(x)});

// 一段時(shí)間后:
unsubscribe(); // 終止

使用Observable、 Observer 和 Subscription這些概念的原因是,我們可以在Observable 契約之下安全、兼容地調(diào)用操作符。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/79350.html

相關(guān)文章

  • RxJS 核心概念Subject

    摘要:返回的對(duì)象同時(shí)是類(lèi)型的,擁有方法。由于調(diào)用后,開(kāi)始執(zhí)行,因此,會(huì)返回一個(gè)供調(diào)用者來(lái)終止執(zhí)行。是的一個(gè)衍生類(lèi),具有最新的值的概念。舉一個(gè)形象的例子,表示一個(gè)人的生日,而則表示一個(gè)人的歲數(shù)。 什么是Subject? 在RxJS中,Subject是一類(lèi)特殊的Observable,它可以向多個(gè)Observer多路推送數(shù)值。普通的Observable并不具備多路推送的能力(每一個(gè)Observer...

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

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

    RebeccaZhong 評(píng)論0 收藏0
  • RxJS 核心概念Observer & Subscription

    摘要:在中,是一個(gè)由回調(diào)函數(shù)組成的對(duì)象,鍵名分別為和,以此接受推送的不同類(lèi)型的通知,下面的代碼段是的一個(gè)示例調(diào)用邏輯,只需在訂閱后將傳入在中,是可選的。當(dāng)然你也可以將和的回調(diào)函數(shù)分別傳入什么是是一個(gè)代表可以終止資源的對(duì)象,表示一個(gè)的執(zhí)行過(guò)程。 Observer(觀察者) 什么是Observer? Observer(觀察者)是Observable(可觀察對(duì)象)推送數(shù)據(jù)的消費(fèi)者。在RxJS中,O...

    tinysun1234 評(píng)論0 收藏0
  • RxJS和react開(kāi)發(fā)mac地址輸入框

    摘要:項(xiàng)目簡(jiǎn)介本次使用了和開(kāi)發(fā)了一個(gè)地址輸入框,主要實(shí)現(xiàn)的功能有限制輸入符合條件的字符并每隔兩位可以自動(dòng)添加用于分割的冒號(hào)。項(xiàng)目屏蔽了的事件處理,同時(shí)使用來(lái)手動(dòng)控制光標(biāo)。繼承于和因此同時(shí)具有和兩者的方法。后面的和都是需要利用最新的來(lái)進(jìn)行判斷的。 項(xiàng)目簡(jiǎn)介 本次使用了RxJS和react開(kāi)發(fā)了一個(gè)mac地址輸入框,主要實(shí)現(xiàn)的功能有限制輸入符合條件的字符1-9,a-f,并每隔兩位可以自動(dòng)添加用于...

    CastlePeaK 評(píng)論0 收藏0
  • 從觀察者模式到迭代器模式系統(tǒng)講解 RxJS Observable(一)

    摘要:是的縮寫(xiě),起源于,是一個(gè)基于可觀測(cè)數(shù)據(jù)流結(jié)合觀察者模式和迭代器模式的一種異步編程的應(yīng)用庫(kù)。是基于觀察者模式和迭代器模式以函數(shù)式編程思維來(lái)實(shí)現(xiàn)的。學(xué)習(xí)之前我們需要先了解觀察者模式和迭代器模式,還要對(duì)流的概念有所認(rèn)識(shí)。 RxJS 是 Reactive Extensions for JavaScript 的縮寫(xiě),起源于 Reactive Extensions,是一個(gè)基于可觀測(cè)數(shù)據(jù)流 Stre...

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

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

0條評(píng)論

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