[英]What is the difference between Observable.lift and Observable.pipe in rxjs?
[英]What is the difference between Observable and a Subject in rxjs?
在流編程中有兩個主要接口: Observable和Observer 。
Observable是針對消費者的,它可以被轉化和訂閱:
observable.map(x => ...).filter(x => ...).subscribe(x => ...)
Observer是用於提供可觀察源的接口:
observer.next(newItem)
我們可以使用Observer創建新的Observable :
var observable = Observable.create(observer => {
observer.next('first');
observer.next('second');
...
});
observable.map(x => ...).filter(x => ...).subscribe(x => ...)
或者,我們可以使用同時實現Observable和Observer接口的Subject :
var source = new Subject();
source.map(x => ...).filter(x => ...).subscribe(x => ...)
source.next('first')
source.next('second')
Observable 設計為單播,Subjects 設計為多播。
如果您查看下面的示例 -每個訂閱都會收到不同的值作為設計為單播開發的 observable。
import {Observable} from 'rxjs';
let obs = Observable.create(observer=>{
observer.next(Math.random());
})
obs.subscribe(res=>{
console.log('subscription a :', res); //subscription a :0.2859800202682865
});
obs.subscribe(res=>{
console.log('subscription b :', res); //subscription b :0.694302021731573
});
如果您期望訂閱的值相同,這可能會很奇怪。
我們可以使用 Subjects 來解決這個問題。 主題類似於事件發射器,它不會為每個訂閱調用。 考慮下面的例子。
import {Subject} from 'rxjs';
let obs = new Subject();
obs.subscribe(res=>{
console.log('subscription a :', res); // subscription a : 0.91767565496093
});
obs.subscribe(res=>{
console.log('subscription b :', res);// subscription b : 0.91767565496093
});
obs.next(Math.random());
兩個訂閱都獲得了相同的輸出值!。
可觀察對象
他們很冷漠:當他們至少有一個觀察者時,代碼就會被執行。
創建數據副本:Observable 為每個觀察者創建數據副本。
單向:Observer 不能為 observable(origin/master)賦值。
代碼將為每個觀察者運行。 如果是 HTTP 調用,則每個觀察者都會調用它。
如果它是我們想要在所有組件之間共享的服務,它不會有最新結果所有新訂閱者仍將訂閱相同的 observable 並從頭開始獲取價值
單播意味着可以從 observable 發出值,而不是從任何其他組件發出值。
主題
它們很熱:即使沒有觀察者,代碼也會被執行並且值會被廣播。
共享數據:在所有觀察者之間共享相同的數據。
雙向:Observer 可以為 observable(origin/master) 賦值。
如果使用 using 主題,那么您將錯過在創建觀察者之前廣播的所有值。 所以這里來了重播主題
多播,可以將值投射到多個訂閱者,並且可以同時充當訂閱者和發射者
請參閱 rxjs 文檔(更多信息和示例): http ://reactivex.io/rxjs/manual/overview.html#subject
什么是主題? RxJS Subject 是一種特殊類型的 Observable,它允許將值多播到許多觀察者。 雖然普通的 Observable 是單播的(每個訂閱的 Observer 擁有一個獨立的 Observable 執行),但主題是多播的。
一個 Subject 就像一個 Observable,但可以多播給許多觀察者。 主題就像 EventEmitters:它們維護着許多偵聽器的注冊表。
和代碼,擴展Observable
Subject
: https : //github.com/ReactiveX/rxjs/blob/master/src/internal/Subject.ts#L22
/**
* @class Subject<T>
*/
export class Subject<T> extends Observable<T> implements SubscriptionLike {
//...
}
Observable 只能通知一個觀察者,而 Subject 可以通知多個觀察者。
我發現接受的答案有點令人困惑!
Observer不是用於提供Observable源的接口,而是用於觀察Observable源的接口……從名稱上看更有意義,對嗎?
所以,原因是:
var observable = Observable.create(observer => {
observer.next('first');
observer.next('second');
...
});
工作 - 創建一個發出“第一個”然后“第二個”的可觀察對象 - Observable.create(...)
的參數是一個訂閱函數,它基本上定義了哪些Observer事件將在該Observable的直接Observer上發生。
如果你想再深入一點,重要的是要理解訂閱函數在你訂閱時不是直接在Observer對象上調用的,而是由一個Subscription對象中介,它可以強制執行正確的可觀察規則,例如Observable永遠不會在調用了observer.complete()
之后發出新值,即使您的 subscribe 函數看起來好像是這樣。
參考: http : //reactivex.io/rxjs/manual/overview.html#creating-observables
一個Subject既是一個Observable又是一個觀察者,再一次,它看起來就像Observer接口是將事件“饋送”給Subject 的方式。 但是,如果您意識到Subject有點像Observable並具有與 subscribe 功能等效的Observable (即,您定義觀察它的事物將發生什么事件),則命名更容易理解,即使在它之后,它也位於對象上已經被創造了。 因此,您在Subject上調用Observer方法來定義觀察它的事物將發生什么Observer事件! 😊(同樣,涉及中間對象,以確保您只能做合法的事情序列。)
從另一個角度來看,注意到訂閱一個 Observable 會重新執行 Observable 函數是好的。 例如,如果數據源是服務,這可能會導致性能問題。
如果您希望多個訂閱者獲得相同的值,您可能需要一個 Subject 。 為此,請確保在主題訂閱數據源之前設置您的訂閱。 否則,您的過程將被卡住。
更多細節在這里: https : //javascript.tutorialhorizon.com/2017/03/23/rxjs-subject-vs-observable/
想象一下,如果您有一個數據流進入您的應用程序,就像在 websocket 連接中一樣。 你想要一種方法來處理它。 有幾個解決辦法:
1.普通ajax請求:這個方案不可行,因為不適用於處理推送數據。 與其說是推,不如說是拉。
2. Promise:也不好,因為你必須觸發它們並且它們只能檢索一次。 也更多的是拉然后推。
所以為了取回這個數據,在過去,我們做一個長輪詢。 例如,我們在這里設置了一個間隔函數來每 1 分鍾檢索一次該數據流。 雖然它有效,但它實際上加重了 CPU 和內存等資源的負擔。
但現在有了選項 3,
3. Observable:你可以訂閱並讓數據流不停地進來,直到函數完成被調用。
酷吧? 但是還有另一個問題。 如果您只想在應用程序中的某處觀察一次傳入數據,該怎么辦? 但是您希望在數據到達時在您的應用程序周圍同時使用該數據。 那是您何時何地使用主題。 您將 subject.subscribe() 放在您希望在整個應用程序中使用的地方。 當數據到達時,有subject.subscribe() 的地方會同時處理它們。 但是觀察者必須像這樣訂閱主題作為其參數。
觀察者.訂閱(主題)。
示例應用程序是當您想要構建通知警報時。
您不能對同一個 observable 進行多個訂閱,因為很有可能每個訂閱者都會收到不同的輸入數據。 但是對於主題,所有通過主題 subscribe() 的操作都將檢索相同的數據。
另一個類比是通過雜志訂閱。 每個訂閱者都會收到帶有他們名字的雜志。 所以,不同的訂閱 = 不同的接收者姓名。(Normal Observable)但是當你與你的朋友分享時,你所有的朋友都會收到同樣的雜志,上面只有你的名字。(Normal Observable with Subject)
這家伙用代碼示例很好地解釋了它。 您可以在https://javascript.tutorialhorizon.com/2017/03/23/rxjs-subject-vs-observable/查看
希望這個答案有幫助。
Observable :只有 Observable 知道如何以及何時在 observable 上觸發事件。 即next()
方法只能在實例化的構造函數中調用。 此外,每次訂閱時,都會創建一個單獨的觀察者,並僅在構造函數內部使用特定的觀察者調用next()
方法,在以下示例中, subscriber
本身就是觀察者,並且在實例化的構造函數執行時訂閱它。 前任:
import { Observable } from 'rxjs';
const observable = new Observable(subscriber => {
subscriber.next(1);
subscriber.next(2);
setTimeout(() => {
subscriber.next(3);
}, 1000);
});
Subject :這里的next()
方法可以在構造函數之外的任何地方被主題使用。 此外,在訂閱之前調用next()
方法時,將錯過特定事件。 因此,只有在訂閱后才必須調用next()
方法。 前任:
import { Subject } from 'rxjs';
const subject = new Subject<number>();
subject.next(1); // this is missed
subject.subscribe({
next: (v) => console.log(`observerA: ${v}`)
});
subject.subscribe({
next: (v) => console.log(`observerB: ${v}`)
});
subject.next(2);
簡要地,
主題:您可以發送到它並從中接收。
觀察到的:你可以從它只能接收。
換句話說,在主題中你可以訂閱它,你可以使用它隨時隨地在代碼中廣播給其他訂閱者。
同時,在觀察到你只能訂閱(它初始化之后,你不能用它來廣播數據)。 唯一可以從 observable 廣播數據的地方是它的構造函數內部。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.