有人可以解释 Angular 中Promise和Observable之间的区别吗?
每个例子都有助于理解这两种情况。在什么情况下我们可以使用每个案例?
诺言
当异步操作完成或失败时, Promise处理单个事件 。
注意:有Promise库支持取消,但 ES6 Promise到目前为止还没有。
可观察
Observable就像一个Stream (在许多语言中),允许传递零个或多个事件,其中为每个事件调用回调。
通常Observable比Promise更Promise因为它提供了Promise等功能。使用Observable ,如果要处理 0,1 或多个事件并不重要。您可以在每种情况下使用相同的 API。
Observable还有优于Promise的优势可以取消 。如果不再需要对服务器的 HTTP 请求或其他一些昂贵的异步操作的结果,则Observable的Subscription允许取消订阅,而Promise最终会调用成功或失败的回调,即使您没有需要通知或它提供的结果。
Observable 提供了map , forEach , reduce等操作符 ,类似于数组
还有强大的运算符,如retry()或replay() ,... 通常非常方便。
Promises和Observables为我们提供了抽象,帮助我们处理应用程序的异步性质。 @Günter 和 @Relu 清楚地指出了它们之间的区别。
由于代码片段胜过千言万语,让我们通过下面的示例更容易理解它们。
感谢 @Christoph Burgdorf 的精彩文章
Angular 使用 Rx.js Observables 而不是 promises 来处理 HTTP。
假设您正在构建一个搜索功能 ,该功能可以在您键入时立即显示结果。听起来很熟悉,但这项任务带来了很多挑战。
HTTP请求。基本上,我们只想在用户停止键入而不是每次按键时都点击它。 该演示将只包含两个文件: app.ts和wikipedia-service.ts 。但在现实世界中,我们很可能会将事情进一步分解。
下面是基于 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 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);
}
}这里也没有什么惊喜。我们注入WikipediaService并通过搜索方法将其功能暴露给模板。模板只是绑定到keyup并调用search(term.value) 。
我们打开了Promise的结果,即 WikipediaService 的搜索方法返回并将其作为一个简单的字符串数组暴露给模板,以便我们可以通过它*ngFor循环*ngFor并为我们构建一个列表。
Observables真正发光的地方
让我们改变我们的代码,不要在每次击键时敲击端点,而只是在用户停止键入400 ms时才发送请求
为了揭示这样的超能力,我们首先需要获得一个带有用户输入的搜索词的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> ,当没有 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));
}
}发送我们的应用已经显示结果的搜索字词的另一个请求将浪费资源。为了达到理想的行为,我们所要做的就是在调用debounceTime(400)后立即调用distinctUntilChanged操作符
要处理无序响应,请查看完整的文章http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html
至于我在 Angular 中使用 Http,我同意在正常使用情况下使用 Observable 而不是 Promise 没有太大区别。在实践中,这些优点都没有真正相关。希望将来可以看到一些高级用例:)
学到更多