angular - rxjs




Promises和Observables有什麼區別? (16)

有人可以解釋Angular中 PromiseObservable 之間的區別嗎?

每個例子都有助於理解這兩種情況。 在什麼情況下我們可以使用每個案例?


Promises和Observable都幫助我們處理異步操作。 這些異步操作完成後,它們可以調用某些回調。

Angular使用來自RxJS的Observables而不是用於處理HTTP的promise

Below are some important differences in promises & Observables.


以下是承諾和觀察中的一些重要差異。

諾言

  • 僅發出單個值
  • 不可取消
  • 不可共享
  • 始終異步

可觀察

  • 發出多個值
  • 僅在被調用或有人訂閱時執行
  • 可以取消
  • 可以由多個訂閱者共享和訂閱該共享值。 所有訂閱者都將在一個時間點執行。
  • 可能異步

有關更好的理解,請參閱 https://stackblitz.com/edit/observable-vs-promises


首先是Promise vs Observable相似度

  1. 兩者都用於處理異步代碼。
  2. 請尋找承諾的例子。 Promise構造函數傳遞一個解析引用函數,該函數在完成某些異步任務時調用某些值時將被調用。
ngOnInit() {
  // promise api
  this.service.getData().then(d => {
     this.data = d;
     this.changeDetectorRef.detectChanges();
  });

  // observable api
  this.service.getData().pipe(takeUntil(this.unsubscribe)).subscribe((d) => {
     this.data = d;
     this.changeDetectorRef.detectChanges();
  });
}
  1. 現在可以觀察到的例子。 這裡我們還將一個函數傳遞給observable,一個觀察者來處理異步任務。 與承諾中的決心不同,它具有以下方法並且代替當時訂閱。

  2. 所以兩者都處理異步任務。 現在讓我們看看差異。

var promise_eg = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve('foo');
  }, 300);
});

promise_eg.then(function(value) {
  console.log(value);
  // expected output: "foo"
});

console.log(promise_eg);

承諾與可觀察的差異

諾言

  1. 它解析或拒絕單個值,並且可以一次處理單個值的異步任務。
  2. 承諾一旦解決了它完成的異步值,就不能再使用了。只是一次性使用而且這裡不足。
  3. 不可取消
  4. 沒有rxjs支持運營商。

可觀察

  1. 能夠發出多個異步值。
  2. 用於處理事件或值的流。 考慮到你有一個包含眾多任務或值的數組,並且你希望每次插入值都應該自動處理。 無論何時將值推入此數組,其所有訂閱者都將自動接收最新值。
  3. Observable對於觀察輸入更改,重複間隔,所有子組件的廣播值,Web套接字推送通知等非常有用。
  4. 可以隨時使用取消訂閱方法取消。
  5. 承諾的最後一個好的部分是支持rxjs運算符。 您有許多管道運算符主要是map,filter,switchMap,combineLatest等,以便在訂閱之前轉換可觀察數據。


諾言:

  • 提供單一的未來價值;
  • 不懶惰;
  • 不可取消;

觀察到:

  • 隨著時間的推移發出多個值;
  • 懶;
  • 撤銷;
  • 支持map,filter,reduce和類似的運算符

如果您願意,可以在Angular中調用HTTP時使用promises而不是observable。


可觀察和承諾之間的基本區別是:


我在第一次閱讀本教程時遇到的問題並不明顯,而docs則是多播的想法。

確保您知道默認情況下,多個訂閱將觸發Observable中的多個執行。 對單個HTTP調用的多個訂閱Observable將觸發多個相同的HTTP調用,除非您 .share() (啟用多播)。

一個承諾迫使你一次處理一件事,打開它的數據,處理異常,對async / await之類的酷事提供語言支持,否則就是非常準確的。

Observable有許多花里胡哨的東西,但你需要了解你正在使用的功能,否則它可能會被濫用。


關於這個主題已經有很多答案,所以我不會添加冗餘的答案。

但對於剛剛開始學習 Observable / Angular的人 並想知道哪一個與 Promise相比 ,我建議你保留一切Observable並將項目中所有現有的 Promise 轉換為Observable。

僅僅因為Angular框架本身及其社區都使用Observable。 因此,當您集成框架服務或第三方模塊並將所有內容鏈接在一起時,這將是有益的。

雖然我欣賞所有的downvotes,但我仍然堅持我的觀點,除非有人發表適當的評論列出一些可能在你的Angular項目中使用Promises over Observables仍然有用的場景。

當然,沒有任何意見在所有情況下100%正確,但至少我認為98%的時間用於Angular框架中的常規商業項目,Observable是正確的方法。

即使你在簡單的愛好項目的起點不喜歡它,你很快就會意識到你在Angular中幾乎所有與之交互的組件,並且大多數Angular友好的第三方框架都使用了Observables,然後你就會最後不斷將你的Promise轉換為Observable以便與他們溝通。

這些組件包括但不限於:HttpClient,表單構建器,角度材料模塊/對話框,Ngrx存儲/效果和ngx-bootstrap。

事實上,我在過去兩年中處理的角度生態系統的唯一承諾是 APP_INITIALIZER


雖然接受的答案總體上是好的,但我認為它並不強調在處理Angular組件時,你幾乎總是想要使用Observable,因為它支持取消。 Promise無法取消,即使您的組件被銷毀也會解決。 角度往往是寬容的,直到它不是。

例如,對已銷毀組件的任何手動更改檢測都將導致異常:

Rx.Observable.fromEvent(button, "click"),
Rx.Subject()

如果在解析promise之前銷毀了組件,則在解析 attempt to use destroyed view promise時 會出現 錯誤。

或者,如果您使用帶有 takeUntil 模式 的 takeUntil ,那麼只要您的組件被銷毀,訂閱就會被取消。

這是一個人為的例子,但是為被破壞的組件執行代碼可能會導致錯誤。 除非你出於某種原因真的想這樣做:p


即使這個答案很晚,我總結了下面的差異,

觀察到:

  1. Observable只是一個 function ,它接受 an observer 並返回一個 function Observer: an object with next, error.
  2. Observer允許 subscribe/unsubscribe 其數據流,向觀察者發出下一個值, notify 觀察者 errors 並通知觀察者 stream completion
  3. Observer提供了一個 function to handle next value ,錯誤和流結束的 function to handle next value (ui事件,http響應,帶有Web套接字的數據)。
  4. 隨著時間的推移使用 multiple values
  5. 它是 cancel-able/retry-able ,支持 map,filter,reduce 等運算符。
  6. 創建Observable可以是 - Observable.create() - 返回可以調用方法的 Observer Observable.from() - Observer Observable.from() - 將數組或者iterable轉換為 - Observable Observable.fromEvent() - 將事件轉換為Observable - Observable.fromPromise() - 將Promise轉換為Observable - Observable.range() - 返回指定範圍內的整數序列

承諾

  1. 承諾代表著將來完成的任務;

  2. 承諾 resolved by a value ;

  3. 承諾被例外拒絕;

  4. 不可 cancellable ,它返回 a single value

  5. 承諾暴露一個函數 (then)

    然後返回一個新的 promise ;

    - attachment 將根據 state 執行;

    - guaranteed handlers order attached 執行;


在答案中缺少Observables的一個缺點。 Promise允許使用ES7 async / await函數。 使用它們,您可以編寫異步代碼,就像它是同步函數調用一樣,因此您不再需要回調。 Observables執行此操作的唯一可能性是將它們轉換為Promises。 但是當你將它們轉換為Promises時,你只能再次獲得一個返回值:

async function getData(){
    const data = await observable.first().toPromise();
    //do stuff with 'data' (no callback function needed)
}

進一步閱讀: 如何在Rx Observable上“等待”?


我相信所有其他答案都應該清除你的疑慮。 不過,我只是想補充說,observables是基於函數式編程的,我發現它附帶的函數非常有用,如map,flatmap,reduce,zip。 Web實現的一致性,特別是當它依賴於API請求時,是一種殘酷的改進。

我強烈推薦 這個文檔 ,因為它是reactiveX的官方文檔,我發現它是最明確的。

如果你想進入observables,我會建議這個由3部分組成的帖子: http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/

雖然它適用於RxJava,但概念是相同的,並且它的解釋非常好。 在reactiveX文檔中,您具有每個函數的等價性。 你必須尋找RxJS。


承諾 - 提供單一的未來價值。 不懶惰。 不可取消。 它會拒絕或解決。

可觀察 - 提供多種未來價值。 懶惰。 可以取消。 它提供其他方法實時地圖,過濾,減少。


簡短回答:

觀察到的 更好的 ,它具有所有 承諾 的功能,以及額外的功能。

答案很長:

公司承諾:

  • 一次性使用“一次返回數據”
  • 沒有取消
  • 一個聽眾
  • 沒有套接字支持一個監聽器

觀察到:

  • 數據更改時多次返回數據
  • 支持取消
  • 支持插座
  • 支持多個Listener,並在數據更改時通知他們
  • 支持地圖,過濾,減少

諾言:

異步事件處理程序 - Promise對象表示異步操作的最終完成(或失敗)及其結果值。

語法: new Promise(executor);

例如:

import { range } from 'rxjs';
import { map, filter } from 'rxjs/operators';

range(1, 200).pipe(
  filter(x => x % 2 === 1),
  map(x => x + x)
).subscribe(x => console.log(x));

關於Promise: 它有一個管道,所以它在調用時只返回一次值。 它的單向處理程序,所以一旦調用你可能無法取消。 你可以玩的有用語法, when() then()

觀測:

Observable是隨時間變化的多個值的惰性集合。 對於異步操作來說,它確實是一個很好的方法 它可以用 rxjs 完成, 它具有跨平台支持可以用於角度/反應等。

它的行為像流線。 可以是多管道。 因此,一旦定義,您可以訂閱在許多地方獲得返回結果。

語法: import * as Rx from "@reactivex/rxjs"; to init:

function cancellablePromise(body) {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res; reject = rej;
    body(resolve, reject)
  })
  promise.resolve = resolve;
  promise.reject = reject;
  return promise
}

// Example 1: Reject a promise prematurely
const p1 = cancellablePromise((resolve, reject) => {
  setTimeout(() => resolve('10', 100))
})

p1.then(value => alert(value)).catch(err => console.error(err))
p1.reject(new Error('denied')) // expect an error in the console

// Example: Resolve a promise prematurely
const p2 = cancellablePromise((resolve, reject) => {
  setTimeout(() => resolve('blop'), 100)
})

p2.then(value => alert(value)).catch(err => console.error(err))
p2.resolve(200) // expect an alert with 200

等等

認購: RxLogger.getInstance();

例如:

const promise = new Promise(resolve => {
  setTimeout(() => {
    resolve("Hello from a Promise!");
  }, 2000);
});

promise.then(value => console.log(value));

因為它支持多管道,你可以在不同的位置訂閱結果, 它有很多可能性而不是承諾。

用法: 它有更多的可能性 map, filter, pipe, map, concatMap etc


承諾

  1. 定義:幫助您異步運行函數,並使用它們的返回值(或異常),但 執行 一次
  2. 不懶惰
  3. 不可取消(有支持取消的Promise庫,但到目前為止還沒有ES6 Promise)。 兩個可能的決定是
    • 拒絕
    • 解決
  4. 無法 重試 (Promise應該可以訪問返回承諾具有重試功能的原始函數,這是一種不好的做法)

觀測

  1. 定義:幫助您異步運行函數,並在執行時以連續順序( 多次 )使用它們的返回值。
  2. 默認情況下,它是Lazy,因為它會在時間進展時發出值。
  3. 有很多運營商可以簡化編碼工作。
  4. 如果我們需要根據某些條件重試 obtryable, 則可以使用一次運算符 重試 來重試。如果可以使用,則重試。

    注意 RxMarbles.com 提供了運營商列表及其交互式圖表


諾言

當異步操作完成或失敗時, Promise 處理 單個事件

注意:有 Promise 庫支持取消,但ES6 Promise 到目前為止還沒有。

可觀察

Observable 類似於 Stream (在許多語言中),允許傳遞零個或多個事件,其中為每個事件調用回調。

通常 ObservablePromisePromise 因為它提供了 Promise 等功能。 使用 Observable ,如果要處理0,1或多個事件並不重要。 您可以在每種情況下使用相同的API。

Observable 還有優於 Promise 的優勢可以 取消 。 如果不再需要對服務器的HTTP請求或其他一些昂貴的異步操作的結果,則 ObservableSubscription 允許取消訂閱,而 Promise 最終會調用成功或失敗的回調,即使您不這樣做需要通知或它提供的結果。

Observable提供了 mapforEachreduce 操作符 ,類似於數組

還有強大的運算符,如 retry()replay() ,...通常非常方便。





angular-observable