StackOverflow 上的探讨:What is the difference between Promises and Observables?
得赞最高的一个答复:1777 赞
当异步操作实现或失败时,Promise 会解决单个事件。
留神:有 Promise 库反对 cancellation 操作,但 ES6 Promise 到目前为止还不反对。
Observable
一个 Observable 就像一个 Stream(在许多语言中),容许传递零个或多个事件,其中为每个事件调用回调。
通常 Observable 比 Promise 更受欢迎,因为它提供了 Promise 的个性等等。应用 Observable,您是否要解决 0、1 或多个事件并不重要。您能够在每种状况下应用雷同的 API。
Observable 还比 Promise 具备可勾销的劣势。如果不再须要对服务器的 HTTP 申请或其余一些低廉的异步操作的后果,Observable 的订阅容许勾销订阅,而 Promise 最终会调用胜利或失败的回调,即便你不这样做不再须要告诉或它提供的后果。
尽管 Promise 会立刻启动,但 Observable 只有在您订阅它时才会启动。这就是为什么 Observable 被称为懈怠的起因。
Observable 提供了 map、forEach、reduce 等运算符,用法相似于数组。
还有一些弱小的操作符,如 retry() 或 replay() 等,它们通常十分不便。
提早执行容许在通过订阅执行 observable 之前建设一系列操作符,以进行更具申明性的编程。
排名第二的答复:374 赞
举例说明。
Angular 应用 Rx.js Observables 而不是 promises 来解决 HTTP。
假如您正在构建一个搜寻性能,该性能应在您键入时立刻显示后果。 听起来很相熟,但这项工作会带来很多挑战。
咱们不想在用户每次按下一个键时都拜访服务器端点,如果这样做的话,服务器会被大量的 HTTP 申请吞没。 基本上,咱们只想在用户进行输出后触发 HTTP 申请,而不是每次击键时触发。
对于后续申请,不要应用雷同的查问参数拜访搜寻端点。
解决无序响应。 当咱们同时有多个申请进行中时,咱们必须思考它们以意外程序返回的状况。 设想一下,咱们首先键入 computer,进行,发出请求,而后键入 car,进行,发出请求。 当初咱们有两个正在进行的申请。 可怜的是,携带后果给computer 的申请在携带后果给 car 的申请之后返回。
首先看如何用 promise 实现这个需要。当然,上文提到的所有边界状况都没有解决。
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]); }}
咱们正在注入 Jsonp 服务,以应用给定的搜索词对 Wikipedia API 收回 GET 申请。 请留神,咱们调用 toPromise 是为了从 Observable<Response> 到 Promise<Response>。 最终以 Promise<Array<string>> 作为咱们搜寻办法的返回类型。
app.ts 的实现:
// check the plnkr for the full list of importsimport {...} 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); }}
这里也没什么惊喜。 咱们注入咱们的 WikipediaService 并通过搜寻办法向模板公开它的性能。 该模板简略地绑定到 keyup 并调用 search(term.value)。
咱们解开 WikipediaService 的搜寻办法返回的 Promise 的后果,并将其作为一个简略的字符串数组公开给模板,这样咱们就能够让 *ngFor 循环遍历它并为咱们构建一个列表。
Where Observables really shine
让咱们更改咱们的代码,不要在每次击键时敲击端点,而是仅在用户进行输出 400 毫秒时发送申请
为了揭示这样的超能力,咱们首先须要取得一个 Observable<string> ,它携带用户输出的搜索词。 咱们能够利用 Angular 的 formControl 指令,而不是手动绑定到 keyup 事件。 要应用此指令,咱们首先须要将 ReactiveFormsModule 导入到咱们的利用程序模块中。
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 {}
导入后,咱们能够在模板中应用 formControl 并将其设置为名称“term”。
<input type="text" [formControl]="term"/>
在咱们的组件中,咱们从@angular/form 创立了一个 FormControl 的实例,并将其公开为组件上名称 term 下的一个字段。
在幕后,term 主动公开一个 Observable<string> 作为咱们能够订阅的属性 valueChanges。 当初咱们有了一个 Observable<string>,取得用户输出就像在咱们的 Observable 上调用 debounceTime(400) 一样简略。 这将返回一个新的 Observable<string>,它只会在 400 毫秒内没有新值呈现时才收回新值。
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)); }}
对咱们的应用程序曾经显示后果的搜索词收回另一个申请将是一种资源节约。 为了实现所需的行为,咱们所要做的就是在咱们调用 debounceTime(400) 之后立刻调用 distinctUntilChanged 运算符。
Observable 和 promise 的比拟:
更多Jerry的原创文章,尽在:"汪子熙":