Sự khác biệt giữa Promise
và Observable
trong Angular là gì?
Một ví dụ trên mỗi sẽ hữu ích trong việc hiểu cả hai trường hợp. Trong kịch bản nào chúng ta có thể sử dụng từng trường hợp?
Sự khác biệt giữa Promise
và Observable
trong Angular là gì?
Một ví dụ trên mỗi sẽ hữu ích trong việc hiểu cả hai trường hợp. Trong kịch bản nào chúng ta có thể sử dụng từng trường hợp?
Câu trả lời:
Lời hứa
Một Promise
xử lý một sự kiện duy nhất khi một hoạt động không đồng bộ hoàn thành hoặc thất bại.
Lưu ý: Có những Promise
thư viện ngoài đó hỗ trợ hủy bỏ, nhưng ES6 Promise
cho đến nay vẫn chưa có.
Có thể quan sát
An Observable
giống như một Stream
(trong nhiều ngôn ngữ) và cho phép vượt qua 0 hoặc nhiều sự kiện trong đó gọi lại được gọi cho mỗi sự kiện.
Thường Observable
được ưa thích hơn Promise
bởi vì nó cung cấp các tính năng của Promise
và nhiều hơn nữa. Với Observable
nó không thành vấn đề nếu bạn muốn xử lý 0, 1 hoặc nhiều sự kiện. Bạn có thể sử dụng cùng một API trong từng trường hợp.
Observable
cũng có lợi thế hơn Promise
để được hủy bỏ . Nếu kết quả của một yêu cầu HTTP đến một máy chủ hoặc một số hoạt động async đắt khác là không cần thiết nữa, các Subscription
của một Observable
phép hủy đăng ký, trong khi một Promise
cuối cùng sẽ gọi sự thành công hay thất bại callback ngay cả khi bạn không cần thông báo hoặc kết quả mà nó cung cấp nữa.
Quan sát được cung cấp nhà khai thác như map
, forEach
, reduce
, ... tương tự như một mảng
Ngoài ra còn có các toán tử mạnh như retry()
, hoặc replay()
, ... thường khá tiện dụng.
Promise
, cùng với async
/ await
làm cho mã của bạn phẳng trở lại! Trong phần lớn các tình huống và trong các dự án không liên quan đến khoa học tên lửa, không cần phải viết các hàm lồng nhau khủng khiếp đó bằng các chuỗi phương thức phức tạp không cần thiết. Bạn có thể sử dụng async
/ await
ngay hôm nay với các bộ chuyển mã, thích TypeScript
và viết mã phẳng thực sự có thể đọc được của con người mà không cần bất kỳ rxjs
mẫu nào. Bạn có thể vẫn sẽ cần rxjs
đôi khi trong các tình huống chọn lọc, bởi vì nó thực sự có rất nhiều thứ để cung cấp.
Cả hai Promises
và Observables
cung cấp cho chúng tôi những khái niệm trừu tượng giúp chúng tôi xử lý tính chất không đồng bộ của các ứng dụng của chúng tôi. Sự khác biệt giữa chúng được chỉ ra rõ ràng bởi @ Günter và @Relu.
Vì một đoạn mã có giá trị bằng một ngàn từ, hãy xem qua ví dụ dưới đây để hiểu chúng dễ dàng hơn.
Cảm ơn @Christoph Burgdorf cho bài viết tuyệt vời
Angular sử dụng Rx.js Observables thay vì lời hứa để xử lý HTTP.
Giả sử rằng bạn đang xây dựng một chức năng tìm kiếm sẽ hiển thị ngay kết quả cho bạn khi bạn nhập. Âm thanh quen thuộc nhưng có rất nhiều thử thách đi kèm với nhiệm vụ đó.
HTTP
yêu cầu. Về cơ bản, chúng tôi chỉ muốn nhấn nó một khi người dùng đã ngừng gõ thay vì với mỗi lần nhấn phím.Bản demo sẽ chỉ bao gồm hai tệp: app.ts
và wikipedia-service.ts
. Trong một kịch bản thế giới thực, rất có thể chúng ta sẽ phân chia mọi thứ hơn nữa.
Dưới đây là triển khai dựa trên Promise không xử lý bất kỳ trường hợp cạnh được mô tả nào.
wikipedia-service.ts
import { Injectable } from '@angular/core';
import { URLSearchParams, Jsonp } from '@angular/http';
@Injectable()
export class WikipediaService {
constructor(private jsonp: Jsonp) {}
search (term: string) {
var search = new URLSearchParams()
search.set('action', 'opensearch');
search.set('search', term);
search.set('format', 'json');
return this.jsonp
.get('http://en.wikipedia.org/w/api.php?callback=JSONP_CALLBACK', { search })
.toPromise()
.then((response) => response.json()[1]);
}
}
Chúng tôi đang tiêm Jsonp
dịch vụ để đưa ra GET
yêu cầu đối với API Wikipedia với một thuật ngữ tìm kiếm nhất định. Lưu ý rằng chúng tôi gọi toPromise
để có được từ một Observable<Response>
đến a Promise<Response>
. Cuối cùng kết thúc với Promise<Array<string>>
kiểu trả về của phương thức tìm kiếm của chúng tôi.
app.ts
// check the plnkr for the full list of imports
import {...} from '...';
@Component({
selector: 'my-app',
template: `
<div>
<h2>Wikipedia Search</h2>
<input #term type="text" (keyup)="search(term.value)">
<ul>
<li *ngFor="let item of items">{{item}}</li>
</ul>
</div>
`
})
export class AppComponent {
items: Array<string>;
constructor(private wikipediaService: WikipediaService) {}
search(term) {
this.wikipediaService.search(term)
.then(items => this.items = items);
}
}
Không có nhiều bất ngờ ở đây. Chúng tôi tiêm WikipediaService
và hiển thị chức năng của nó thông qua phương pháp tìm kiếm vào mẫu. Mẫu chỉ đơn giản là liên kết với keyup và các cuộc gọi search(term.value)
.
Chúng tôi mở ra kết quả của Promise rằng phương thức tìm kiếm của WikipediaService trả về và hiển thị nó dưới dạng một chuỗi các chuỗi đơn giản cho mẫu để chúng tôi có thể *ngFor
lặp qua nó và xây dựng một danh sách cho chúng tôi.
Xem ví dụ về triển khai dựa trên Promise trên Plunker
Nơi quan sát thực sự tỏa sáng
Hãy thay đổi mã của chúng tôi để không làm hỏng điểm cuối với mỗi lần nhấn phím mà thay vào đó chỉ gửi yêu cầu khi người dùng ngừng gõ trong 400 ms
Để tiết lộ những siêu năng lực như vậy, trước tiên chúng ta cần có một Observable<string>
thuật ngữ tìm kiếm mà người dùng nhập vào. Thay vì liên kết thủ công với sự kiện keyup, chúng ta có thể tận dụng formControl
chỉ thị của Angular . Để sử dụng chỉ thị này, trước tiên chúng ta cần nhập ReactiveFormsModule
mô-đun ứng dụng.
app.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { JsonpModule } from '@angular/http';
import { ReactiveFormsModule } from '@angular/forms';
@NgModule({
imports: [BrowserModule, JsonpModule, ReactiveFormsModule]
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
Sau khi nhập, chúng ta có thể sử dụng formControl từ trong mẫu của mình và đặt nó thành tên "hạn".
<input type="text" [formControl]="term"/>
Trong thành phần của chúng tôi, chúng tôi tạo một thể hiện FormControl
từ @angular/form
và hiển thị nó dưới dạng một trường dưới thuật ngữ tên trên thành phần của chúng tôi.
Đằng sau hậu trường, thuật ngữ tự động hiển thị một Observable<string>
tài sản valueChanges
mà chúng ta có thể đăng ký. Bây giờ chúng tôi có một Observable<string>
, khắc phục đầu vào của người dùng dễ dàng như gọi debounceTime(400)
vào chúng tôi Observable
. Điều này sẽ trả về một Observable<string>
giá trị mới sẽ chỉ phát ra một giá trị mới khi chưa có giá trị mới trong 400ms.
export class App {
items: Array<string>;
term = new FormControl();
constructor(private wikipediaService: WikipediaService) {
this.term.valueChanges
.debounceTime(400) // wait for 400ms pause in events
.distinctUntilChanged() // ignore if next search term is same as previous
.subscribe(term => this.wikipediaService.search(term).then(items => this.items = items));
}
}
Sẽ là lãng phí tài nguyên để gửi một yêu cầu khác cho cụm từ tìm kiếm mà ứng dụng của chúng tôi đã hiển thị kết quả. Tất cả những gì chúng ta phải làm để đạt được hành vi mong muốn là gọi cho distinctUntilChanged
nhà điều hành ngay sau khi chúng ta gọidebounceTime(400)
Xem ví dụ về triển khai quan sát trên Plunker
Để xử lý các phản hồi không theo thứ tự, vui lòng kiểm tra toàn bộ bài viết http: // blog. Dùtram.io / anga / 2016/06/06 / takes-nhược điểm -of-observables-in- angular2.html
Theo như tôi đang sử dụng http trong Angular, tôi đồng ý rằng trong các trường hợp sử dụng thông thường, không có nhiều khác biệt khi sử dụng Observable so với Promise. Không có lợi thế nào thực sự có liên quan ở đây trong thực tế. Hy vọng tôi có thể thấy một số trường hợp sử dụng nâng cao trong tương lai :)
Tìm hiểu thêm
Cả Promise và Observables sẽ giúp chúng tôi làm việc với các chức năng không đồng bộ trong JavaScript. Chúng rất giống nhau trong nhiều trường hợp, tuy nhiên, vẫn có một số khác biệt giữa cả hai, hứa hẹn là các giá trị sẽ giải quyết theo asynchronous
cách như các cuộc gọi http . Mặt khác, các đài quan sát xử lý một chuỗi các sự kiện không đồng bộ . Sự khác biệt chính giữa chúng được liệt kê dưới đây:
lời hứa:
có thể quan sát:
Ngoài ra, tôi đã tạo hình ảnh đồ họa cho bạn bên dưới để hiển thị sự khác biệt một cách trực quan:
Promise
là cách sai lầm để suy nghĩ về cách hứa hẹn. Các Promise
's trách nhiệm nó chỉ để xử lý thành công hay thất bại trong một cách tương thích async .. Nếu bạn muốn hủy bỏ một http request bạn hủy theo yêu cầu, không phải là lời hứa, và làm cho kết quả hủy hoặc thực hiện hoặc từ chối lời hứa. jsfiddle.net/greggman/ea0yhd4p
Hứa
Đài quan sát
Một toán tử thử lại có thể được sử dụng để thử lại bất cứ khi nào cần thiết, ngoài ra nếu chúng ta cần thử lại có thể quan sát được dựa trên một số điều kiện thì có thể sử dụng lại.
Lưu ý : Danh sách các toán tử cùng với sơ đồ tương tác của họ có sẵn tại RxMarbled.com
Có một nhược điểm của Observables bị thiếu trong các câu trả lời. Hứa hẹn cho phép sử dụng các chức năng async / await ES7. Với chúng, bạn có thể viết mã không đồng bộ giống như nó sẽ là một cuộc gọi hàm đồng bộ, vì vậy bạn không cần gọi lại nữa. Khả năng duy nhất để Observables thực hiện điều này là chuyển đổi chúng thành Promise. Nhưng khi bạn chuyển đổi chúng thành Lời hứa, bạn chỉ có thể có một giá trị trả lại:
async function getData(){
const data = await observable.first().toPromise();
//do stuff with 'data' (no callback function needed)
}
Đọc thêm: Làm thế nào tôi có thể 'chờ đợi' trên Rx Observable?
Cả Promise và Observables đều chỉ xử lý cuộc gọi không đồng bộ.
Dưới đây là sự khác biệt giữa chúng:
Có thể quan sát
Lời hứa
Mỗi lần chỉ phát ra một giá trị
Gọi các dịch vụ mà không có .then và .catch
Không thể bị hủy
Không cung cấp bất kỳ nhà khai thác
Mặc dù câu trả lời này là muộn, tôi đã tóm tắt những khác biệt dưới đây,
Có thể quan sát:
function
mất an observer
và trả lại một function Observer: an object with next, error.
subscribe/unsubscribe
luồng dữ liệu của nó, phát ra giá trị tiếp theo cho người quan sát, notify
người quan sát errors
và thông báo cho người quan sát vềstream completion
function to handle next value
, lỗi và kết thúc luồng (sự kiện ui, phản hồi http, dữ liệu với ổ cắm web).multiple values
theo thời giancancel-able/retry-able
và hỗ trợ các nhà khai thác như map,filter,reduce
vvObservable.create()
trả về Có thể quan sát có thể gọi các phương thức trên - Observer Observable.from()
- chuyển đổi một mảng hoặc lặp lại thành - Observable Observable.fromEvent()
- chuyển đổi một sự kiện thành Observable - Observable.fromPromise()
- chuyển đổi một Promise thành Observable - Observable.range()
- trả về một chuỗi các số nguyên trong phạm vi cụ thểHứa :
Một lời hứa đại diện cho một nhiệm vụ sẽ hoàn thành trong tương lai;
Hứa sẽ trở thành resolved by a value
;
Lời hứa bị từ chối bởi các ngoại lệ;
Không cancellable
và nó trở lạia single value
Một lời hứa phơi bày một chức năng (then)
-then trả lại một cái mới promise
;
-tất cả cho attachment
điều đó sẽ được thực hiện dựa trên
state
;
- handlers
là guaranteed
để thực hiện trong order attached
;
Tôi vừa giải quyết một vấn đề trong đó Promise là giải pháp tốt nhất và tôi chia sẻ nó ở đây cho bất kỳ ai vấp phải câu hỏi này trong trường hợp nó hữu ích (đây chính xác là câu trả lời tôi đang tìm kiếm trước đó):
Trong một dự án Angular2, tôi có một dịch vụ lấy một số tham số và trả về một danh sách giá trị để điền vào các menu thả xuống trên một biểu mẫu. Khi thành phần biểu mẫu khởi tạo, tôi cần gọi cùng một dịch vụ nhiều lần với các tham số khác nhau để xác định một số menu thả xuống khác nhau, tuy nhiên nếu tôi chỉ xếp hàng tất cả các biến để gọi dịch vụ, chỉ có một biến cuối cùng thành công và lỗi còn lại ngoài. Dịch vụ tìm nạp từ cơ sở dữ liệu chỉ có thể xử lý một yêu cầu tại một thời điểm.
Cách duy nhất để điền thành công tất cả các biến menu thả xuống là gọi dịch vụ theo cách ngăn yêu cầu mới được xử lý cho đến khi yêu cầu cuối cùng kết thúc và cơ chế Promise / .then đã giải quyết vấn đề một cách độc đáo.
fetchValueList(listCode): Promise<any> {
return this.dataSvc.getValueList(listCode, this.stateSvc.currentContext, this.stateSvc.currentLanguageCode)
.map(response => response.json())
.toPromise();
}
initializeDropDowns() {
this.fetchValueList('First-Val-List')
.then(data => {
this.firstValList = data;
return this.fetchValueList('Second-Val-List')
}).then(data => {
this.secondValList = data;
return this.fetchValueList('Third-Val-List')
}).then(data => {
this.thirdValList = data;
}) }
Tôi đã định nghĩa các hàm trong thành phần, và sau đó được gọi là initizeDropDowns () trong ngOnInit.
Hàm fetchValueList trả về một Promise, vì vậy lệnh gọi đầu tiên sẽ chuyển listCode đầu tiên và khi Promise giải quyết, giá trị trả về nằm trong biến dữ liệu trong khối .then nơi chúng ta có thể gán nó cho biến this.firstValList. Vì hàm đã trả về dữ liệu, chúng tôi biết dịch vụ đã kết thúc và sẽ an toàn khi gọi lại với listCode thứ hai, giá trị trả về nằm trong biến dữ liệu trong khối .then tiếp theo và chúng tôi gán nó cho biến this.secondValList.
Chúng ta có thể xâu chuỗi số này nhiều lần theo yêu cầu để điền vào tất cả các biến và trên khối mã cuối cùng, chúng ta chỉ cần bỏ qua câu lệnh return và khối kết thúc.
Đây là trường hợp sử dụng rất cụ thể khi chúng tôi có một dịch vụ cần được gọi nhiều lần khi thành phần khởi tạo và khi dịch vụ phải hoàn thành tìm nạp và trả về giá trị trước khi có thể gọi lại, nhưng trong trường hợp này, phương pháp Promise / .then là lý tưởng.
scan()
để xây dựng một luồng các quan sát liên tiếp. Tuy nhiên, cách tiếp cận của bạn có thể rõ ràng hơn và dễ hiểu hơn.
Tôi tin rằng tất cả các câu trả lời khác sẽ xóa tan nghi ngờ của bạn. Tuy nhiên, tôi chỉ muốn thêm rằng các đài quan sát được dựa trên lập trình chức năng và tôi thấy rất hữu ích các chức năng đi kèm với nó như bản đồ, bản đồ phẳng, thu nhỏ, zip. Tính nhất quán mà web đạt được đặc biệt là khi nó phụ thuộc vào các yêu cầu API là một cải tiến tàn bạo.
Tôi thực sự khuyên bạn nên tài liệu này , vì nó là tài liệu chính thức của ReactiveX và tôi thấy nó là tài liệu rõ ràng nhất hiện có.
Nếu bạn muốn quan sát, tôi sẽ đề xuất bài đăng gồm 3 phần này: http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/
Mặc dù nó có nghĩa là cho RxJava, các khái niệm là như nhau, và nó thực sự được giải thích tốt. Trong tài liệu ReactiveX, bạn có các giá trị tương đương cho từng chức năng. Bạn phải tìm RxJS.
Bạn luôn có thể sử dụng một thiết bị quan sát để xử lý hành vi không đồng bộ vì một thiết bị quan sát có tất cả các chức năng mà một lời hứa cung cấp (+ thêm). Tuy nhiên, đôi khi chức năng bổ sung này mà Observables cung cấp không cần thiết. Sau đó, sẽ là thêm chi phí để nhập một thư viện cho nó để sử dụng chúng.
Sử dụng lời hứa khi bạn có một hoạt động không đồng bộ duy nhất mà bạn muốn xử lý kết quả. Ví dụ:
var promise = new Promise((resolve, reject) => {
// do something once, possibly async
// code inside the Promise constructor callback is getting executed synchronously
if (/* everything turned out fine */) {
resolve("Stuff worked!");
}
else {
reject(Error("It broke"));
}
});
//after the promise is resolved or rejected we can call .then or .catch method on it
promise.then((val) => console.log(val)) // logs the resolve argument
.catch((val) => console.log(val)); // logs the reject argument
Vì vậy, một lời hứa thực thi một số mã trong đó nó giải quyết hoặc từ chối. Nếu giải quyết hoặc từ chối được gọi là lời hứa sẽ chuyển từ trạng thái chờ xử lý sang trạng thái được giải quyết hoặc bị từ chối . Khi trạng thái lời hứa được giải quyết, then()
phương thức được gọi. Khi trạng thái lời hứa bị từ chối, catch()
phương thức được gọi.
Sử dụng Đài quan sát khi có luồng (dữ liệu) theo thời gian mà bạn cần xử lý. Luồng là một chuỗi các yếu tố dữ liệu đang được cung cấp theo thời gian . Ví dụ về các luồng là:
Trong Observable, chính nó được chỉ định khi sự kiện tiếp theo xảy ra, khi xảy ra lỗi hoặc khi Observable hoàn thành . Sau đó, chúng tôi có thể đăng ký để có thể quan sát được, điều này kích hoạt nó và trong đăng ký này, chúng tôi có thể vượt qua 3 cuộc gọi lại (không phải luôn luôn vượt qua tất cả). Một cuộc gọi lại được thực hiện để thành công, một cuộc gọi lại cho lỗi và một cuộc gọi lại để hoàn thành. Ví dụ:
const observable = Rx.Observable.create(observer => {
// create a single value and complete
observer.onNext(1);
observer.onCompleted();
});
source.subscribe(
x => console.log('onNext: %s', x), // success callback
e => console.log('onError: %s', e), // error callback
() => console.log('onCompleted') // completion callback
);
// first we log: onNext: 1
// then we log: onCompleted
Khi tạo một quan sát được, nó đòi hỏi một hàm gọi lại cung cấp cho người quan sát làm đối số. Trên quan sát này, bạn có thể gọi tới onNext
, onCompleted
, onError
. Sau đó, khi Observable được đăng ký, nó sẽ gọi các cuộc gọi lại tương ứng được chuyển vào đăng ký.
Hứa hẹn - Cung cấp một giá trị tương lai duy nhất. Không lười biếng. Không thể hủy bỏ. Nó sẽ từ chối hoặc giải quyết.
Có thể quan sát - Cung cấp nhiều giá trị trong tương lai. Lười biếng . Hủy bỏ có thể. Nó cung cấp các phương pháp khác sống bản đồ, lọc, giảm.
const promise = new Promise(resolve => {
setTimeout(() => {
resolve("Hello from a Promise!");
}, 2000);
});
promise.then(value => console.log(value));
Ví dụ quan sát bây giờ. Ở đây chúng tôi cũng chuyển một chức năng để có thể quan sát, một người quan sát để xử lý tác vụ không đồng bộ. Không giống như giải quyết trong lời hứa, nó có phương thức sau và đăng ký thay thế sau đó.
Vì vậy, cả hai xử lý các nhiệm vụ không đồng bộ. Bây giờ hãy xem sự khác biệt.
const observable = new Observable(observer => {
setTimeout(() => {
observer.next('Hello from a Observable!');
}, 2000);
});
observable.subscribe(value => console.log(value));
Lời hứa
Có thể quan sát
Cả Promise và Observables đều giúp chúng tôi xử lý các hoạt động không đồng bộ. Họ có thể gọi các cuộc gọi lại nhất định khi các hoạt động không đồng bộ này được thực hiện.
Angular sử dụng các thiết bị quan sát từ RxJS thay vì lời hứa để xử lý HTTP
Below are some important differences in promises & Observables.
Lời hứa phát ra một sự kiện duy nhất khi một hoạt động không đồng bộ kết thúc hoặc thất bại.
Một Observable giống như một Luồng (bằng nhiều ngôn ngữ) và cho phép vượt qua ít nhất 0 hoặc nhiều sự kiện trong đó yêu cầu gọi lại cho mọi sự kiện.
Thường xuyên quan sát được ưa thích hơn Promise vì nó mang lại những điểm nổi bật của Promise và hơn thế nữa. Với Observable, không cần thiết nếu bạn cần xử lý 0, 1 hoặc các sự kiện khác nhau. Bạn có thể sử dụng API tương tự cho từng trường hợp.
Promise: lời hứa phát ra một giá trị duy nhất
Ví dụ:
const numberPromise = new Promise((resolve) => {
resolve(5);
resolve(10);
});
numberPromise.then(value => console.log(value));
// still prints only 5
Có thể quan sát: Phát ra nhiều giá trị trong một khoảng thời gian
Ví dụ:
const numberObservable = new Observable((observer) => {
observer.next(5);
observer.next(10);
});
numberObservable.subscribe(value => console.log(value));
// prints 5 and 10
chúng ta có thể nghĩ về một luồng có thể quan sát giống như một luồng phát ra nhiều giá trị trong một khoảng thời gian và cùng một hàm gọi lại được gọi cho mỗi mục được phát ra để có thể quan sát được, chúng ta có thể sử dụng cùng một API để xử lý dữ liệu không đồng bộ. liệu dữ liệu đó được truyền dưới dạng một giá trị hay nhiều giá trị trong một khoảng thời gian.
Lời hứa:
Có thể quan sát:
Promise phát ra một giá trị trong khi Observable phát ra nhiều giá trị. Vì vậy, trong khi xử lý một yêu cầu HTTP, Promise có thể quản lý một phản hồi cho cùng một yêu cầu, nhưng nếu có nhiều phản hồi cho cùng một yêu cầu thì chúng ta phải sử dụng Observable. Có, Observable có thể xử lý nhiều phản hồi cho cùng một yêu cầu.
Lời hứa
const promise = new Promise((data) =>
{ data(1);
data(2);
data(3); })
.then(element => console.log(‘Promise ‘ + element));
Đầu ra
Promise 1
Có thể quan sát
const observable = new Observable((data) => {
data.next(1);
data.next(2);
data.next(3);
}).subscribe(element => console.log('Observable ' + element));
Đầu ra
Observable 1
Observable 2
Observable 3
Dưới đây là một số khác biệt quan trọng trong lời hứa và quan sát.
Lời hứa
Có thể quan sát
Để hiểu rõ hơn, hãy tham khảo https://stackblitz.com/edit/observable-vs-promises
Tôi thấy rất nhiều người sử dụng đối số mà Observable là "có thể hủy được" nhưng việc tầm thường là "không thể hủy bỏ"
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
Câu trả lời ngắn :
Có thể quan sát là tốt hơn , nó có tất cả các tính năng Promise cộng với các tính năng bổ sung.
Câu trả lời dài:
Hứa hẹn:
Có thể quan sát:
Mặc dù câu trả lời được chấp nhận là tốt nói chung, tôi không nghĩ rằng nó nhấn mạnh rằng khi giao dịch với các Thành phần góc, bạn hầu như luôn muốn sử dụng một Đài quan sát vì nó hỗ trợ hủy bỏ. Lời hứa không thể bị hủy và sẽ giải quyết ngay cả khi thành phần của bạn bị hủy. Angular có xu hướng tha thứ cho đến khi nó không.
Ví dụ: mọi phát hiện thay đổi thủ công trên một thành phần bị phá hủy sẽ gây ra ngoại lệ:
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();
});
}
Nếu thành phần của bạn bị hủy trước khi lời hứa được giải quyết, bạn sẽ gặp attempt to use destroyed view
lỗi khi lời hứa được giải quyết.
Ngoài ra, nếu bạn sử dụng các thiết bị quan sát với mẫu TakeUntil , thì ngay khi thành phần của bạn bị hủy, đăng ký sẽ bị hủy.
Đây là một ví dụ giả định nhưng việc thực thi mã cho một thành phần bị phá hủy có thể sẽ dẫn đến lỗi. Trừ khi bạn thực sự muốn làm điều đó vì một số lý do: p
Một cái gì đó tôi gặp phải điều đó không rõ ràng từ lần đọc hướng dẫn đầu tiên và tài liệu là ý tưởng về đa hướng hóa.
Hãy chắc chắn rằng bạn biết rằng theo mặc định, nhiều đăng ký sẽ kích hoạt nhiều lần thực thi trong một Đài quan sát. Nhiều đăng ký cho một cuộc gọi HTTP có thể quan sát được sẽ kích hoạt nhiều cuộc gọi HTTP giống nhau trừ khi bạn .share()
(bật đa tuyến).
Một lời hứa buộc bạn phải giải quyết một vấn đề tại một thời điểm, mở dữ liệu của nó, xử lý các trường hợp ngoại lệ, hỗ trợ ngôn ngữ cho những thứ hay ho như async / await, và là những barebones khá khác.
Một chiếc Observable có rất nhiều chuông và còi, nhưng bạn cần hiểu sức mạnh mà bạn đang làm việc hoặc nó có thể bị lạm dụng.
Lời hứa:
Trình xử lý sự kiện Async - Đối tượng Promise biểu thị sự hoàn thành cuối cùng (hoặc thất bại) của một hoạt động không đồng bộ và giá trị kết quả của nó.
Cú pháp: Promise mới (người thực thi);
Ví dụ:
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);
Về lời hứa: Nó có một đường ống vì vậy, nó sẽ chỉ trả về giá trị một lần khi được gọi. Trình xử lý một chiều của nó vì vậy một khi đã gọi bạn có thể không thể hủy. cú pháp hữu ích bạn có thể chơi xung quanh, khi () và sau đó ()
Đài quan sát:
Đài quan sát là bộ sưu tập lười biếng của nhiều giá trị theo thời gian. nó thực sự là một cách tiếp cận tuyệt vời cho các hoạt động không đồng bộ. nó có thể được thực hiện với rxjs có hỗ trợ đa nền tảng có thể sử dụng với góc / phản ứng, v.v.
nó hoạt động như luồng lót. có thể là nhiều đường ống. vì vậy một khi được xác định, bạn có thể đăng ký để nhận kết quả trả lại ở nhiều nơi.
Cú pháp: import * as Rx from "@reactivex/rxjs";
để init:
Rx.Observable.fromEvent(button, "click"),
Rx.Subject()
Vân vân
để đăng ký: RxLogger.getInstance();
Ví dụ:
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));
vì nó hỗ trợ nhiều đường ống dẫn, bạn có thể đăng ký kết quả ở vị trí khác nhau, nó có nhiều khả năng hơn so với lời hứa.
Cách sử dụng:
nó có nhiều khả năng nhưmap, filter, pipe, map, concatMap etc
Quan sát thường được so sánh với lời hứa. Dưới đây là một số khác biệt chính:
Đài quan sát là khai báo; tính toán không bắt đầu cho đến khi đăng ký. Hứa sẽ thực hiện ngay lập tức khi sáng tạo. Điều này làm cho các quan sát hữu ích để xác định công thức nấu ăn có thể được chạy bất cứ khi nào bạn cần kết quả.
Đài quan sát cung cấp nhiều giá trị. Hứa sẽ cung cấp một. Điều này làm cho các quan sát hữu ích để có được nhiều giá trị theo thời gian.
Quan sát phân biệt giữa chuỗi và thuê bao. Hứa chỉ có mệnh đề .then (). Điều này làm cho các thiết bị quan sát trở nên hữu ích để tạo các công thức biến đổi phức tạp được sử dụng bởi các phần khác của hệ thống, mà không khiến công việc được thực thi.
Observables đăng ký () chịu trách nhiệm xử lý lỗi. Hứa hẹn đẩy lỗi cho trẻ hứa. Điều này làm cho các thiết bị quan sát hữu ích cho việc xử lý lỗi tập trung và có thể dự đoán được.
Đó là sự khác biệt đơn giản nhất mà bạn có thể tìm thấy trên các tài liệu ANGULAR.IO. phần còn lại câu trả lời được đưa ra bởi hầu hết là chính xác tại vị trí của nó
Hứa hẹn chỉ tập trung cho các giá trị đơn lẻ hoặc độ phân giải, các vật thể quan sát là luồng dữ liệu.
Đài quan sát có thể bị hủy nhưng lời hứa không thể bị hủy.
Người ít được biết đến nhất, ít nhất với tôi là
Các quan sát và lời hứa đang giúp chúng tôi làm việc với các chức năng không đồng bộ trong JavaScript / bản thảo. Chúng rất giống nhau trong nhiều trường hợp, tuy nhiên, vẫn có một số khác biệt giữa chúng.
Có rất nhiều câu trả lời về chủ đề này vì vậy tôi sẽ không thêm câu trả lời.
Nhưng với một người mới bắt đầu học Observable / Angular và tự hỏi nên sử dụng cái nào so với Promise , tôi khuyên bạn nên giữ mọi thứ có thể quan sát và chuyển đổi tất cả các Promise hiện có trong dự án của bạn thành Observable.
Đơn giản là vì khung Angular và cộng đồng của nó đều sử dụng Observable. Vì vậy, sẽ rất có lợi khi bạn tích hợp các dịch vụ khung hoặc các mô-đun của bên thứ 3 và kết nối mọi thứ lại với nhau.
Mặc dù tôi đánh giá cao tất cả các downvote nhưng tôi vẫn nhấn mạnh ý kiến của mình ở trên trừ khi có ai đó đưa ra một nhận xét thích hợp để liệt kê một vài tình huống có thể vẫn hữu ích trong dự án Angular của bạn để sử dụng Promise trên Observables.
Tất nhiên, không có ý kiến nào đúng 100% trong mọi trường hợp nhưng ít nhất tôi nghĩ 98% thời gian cho các dự án thương mại thông thường được thực hiện trong khung Angular, Observable là cách đúng đắn.
Ngay cả khi bạn không thích nó ở điểm khởi đầu của dự án sở thích đơn giản của mình, bạn sẽ sớm nhận ra hầu hết tất cả các thành phần bạn tương tác trong Angular và hầu hết khung bên thứ 3 thân thiện của Angular đều sử dụng Observables, và sau đó bạn sẽ cuối cùng đã liên tục chuyển đổi Lời hứa của bạn thành Có thể quan sát được để liên lạc với họ.
Các thành phần này bao gồm nhưng không giới hạn ở: HttpClient, Trình tạo biểu mẫu, mô-đun / hộp thoại vật liệu góc, cửa hàng / hiệu ứng Ngrx và ngx-bootstrap.
Trên thực tế, Lời hứa duy nhất từ hệ sinh thái Angular tôi đã xử lý trong 2 năm qua là APP_INITIALIZER
.