Promises 和 Observables 有什么区别?
What is the difference between Promises and Observables?
Promise
和Angular中的Observable
有什么区别?
每一个例子都有助于理解这两种情况。每个case可以在什么场景下使用?
承诺
A Promise
在异步操作完成或失败时处理 单个事件。
注意:有 Promise
库支持取消,但 ES6 Promise
目前还不支持。
可观察
Observable
类似于 Stream
(在许多语言中)并允许传递零个或多个事件,其中为每个事件调用回调.
通常 Observable
优于 Promise
,因为它提供了 Promise
的功能以及更多。使用 Observable
时,无论您要处理 0、1 还是多个事件都无关紧要。您可以在每种情况下使用相同的 API。
Observable
也比 Promise
有优势 可取消 。如果不再需要对服务器的 HTTP 请求或其他一些昂贵的异步操作的结果,Observable
的 Subscription
允许取消订阅,而 Promise
最终会即使您不再需要通知或它提供的结果,也可以调用成功或失败的回调。
Promise
会立即启动,而 Observable
只有在您订阅后才会启动。这就是 Observable 被称为惰性的原因。
Observable 提供 operators 像 map
, forEach
, reduce
, ... 类似于数组
还有一些强大的运算符,例如 retry()
或 replay()
,...通常非常方便。
A list of operators shipped with rxjs
惰性执行允许在通过订阅执行可观察对象之前建立一个运算符链,以进行更具声明性的编程。
Promises
和 Observables
都为我们提供了抽象,帮助我们处理应用程序的 异步 性质。 和@Relu.
明确指出了它们之间的区别
既然一个代码片段抵得上一千个单词,让我们通过下面的例子来更容易地理解它们。
Thanks @Christoph Burgdorf for the awesome article
Angular 使用 Rx.js Observables 而不是 promises 来处理 HTTP。
假设您正在构建一个搜索功能,它会在您键入时立即显示结果。这听起来很熟悉,但这项任务伴随着很多挑战。
- 我们不想在用户每次按键时都访问服务器端点。它应该用 HTTP 请求的风暴淹没他们。基本上,我们只想在用户停止输入而不是每次击键时点击它。
- 不要为后续请求使用相同的查询参数命中搜索端点。
- 处理乱序响应。当我们同时有多个请求在进行中时,我们必须考虑到它们以意想不到的顺序返回的情况。想象一下,我们首先键入 computer,停止,一个请求发出,我们键入 car,停止,一个请求发出。现在我们有两个正在处理的请求。不幸的是,携带 computer 结果的请求在携带 car.
结果的请求之后返回
该演示仅包含两个文件: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>>
作为我们搜索方法的 return 类型结束。
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 returns 的搜索方法,并将其作为简单的字符串数组公开给模板,以便我们可以让 *ngFor
循环遍历它并为我们建立一个列表。
请参阅 基于 Promise 实施的示例 Plunker
Observables 真正闪耀的地方
让我们更改我们的代码,使其不再在每次击键时敲击端点,而是仅在用户停止输入 400 毫秒
时才发送请求
要揭示这种超能力,我们首先需要获得一个 Observable<string>
来携带用户输入的搜索词。我们可以利用 [=140 代替手动绑定到 keyup 事件=] 的 formControl
指令。要使用此指令,我们首先需要将 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 自动将 Observable<string>
暴露为 属性 valueChanges
我们可以订阅。现在我们有了 Observable<string>
,克服用户输入就像在我们的 Observable
上调用 debounceTime(400)
一样简单。这将 return 一个新的 Observable<string>
只有在 400 毫秒内没有新值出现时才会发出一个新值。
export class App {
items: Array<string>;
term = new FormControl();
constructor(private wikipediaService: WikipediaService) {
this.term.valueChanges
.debounceTime(400) // wait for 400 ms 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 在 Plunker
上的实施示例
For dealing with out-of-order responses, please check the full article
http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html
就我在 Angular 中使用 HTTP 而言,我同意在正常用例中使用 Observable 而不是 Promise 没有太大区别。 None 的优点在实践中非常重要。我希望将来能看到一些高级用例:)
Learn more
承诺
- 定义:帮助您 运行 异步运行,并使用它们的 return 值(或异常),但 仅执行一次。
- 不懒惰
- 不可取消(那里有支持取消的 Promise 库,但 ES6 Promise 目前还不支持)。两个可能的决定是
- 拒绝
- 解决
- 不能重试(Promise 应该可以访问 return 承诺具有重试能力的原始函数,这是一种不好的做法)
Observables
- 定义:帮助您运行异步运行,并在执行时以连续序列(多次)使用它们的return值。
- 默认情况下,它是 lazy,因为它会随着时间的推移发出值。
- 有很多运算符,简化了编码工作。
- 一个运算符retry可用于在需要时重试,如果我们需要根据某些条件重试observable,retryWhen也可以被使用。
注意:运算符列表及其交互图可在此处获得 **RxMarbles.com**
我刚刚处理了一个问题,其中 Promises 是最好的解决方案,如果它有用(这正是我之前寻找的答案),我将在这里分享给任何偶然发现这个问题的人:
在 Angular2 项目中,我有一个服务接受一些参数和 returns 一个值列表来填充表单上的下拉菜单。当表单组件初始化时,我需要使用不同的参数多次调用同一个服务来定义多个不同的下拉菜单,但是如果我简单地排队所有变量来调用服务,只有最后一个成功,其余错误出去。从数据库中获取的服务一次只能处理一个请求。
成功填充所有下拉菜单变量的唯一方法是以一种阻止处理新请求的方式调用服务,直到最后一个请求完成,Promise / .then 机制很好地解决了这个问题.
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;
}) }
我在组件中定义了函数,然后在ngOnInit中调用了initializeDropDowns()。
fetchValueList 函数 return 是一个 Promise,因此第一次调用传递了第一个 listCode,当 Promise 解析时,return 值位于 .then 块中的数据变量中,我们可以在其中将其分配给 this.firstValList 变量。由于函数有 returned 数据,我们知道服务已经完成,可以安全地使用第二个 listCode 再次调用,return 值在下一个 .then 块的数据变量中,我们分配它到 this.secondValList 变量。
我们可以根据需要多次链接它以填充所有变量,在最后一个代码块上我们只需省略 return 语句并且块终止。
这是一个非常具体的用例,其中我们有一个服务需要在组件初始化时多次调用,并且该服务必须先完成其获取和 return 一个值才能完成再次调用,但在这种情况下,Promise / .then 方法是理想的。
Promises 和 Observables 都将帮助我们使用 异步功能 JavaScript。它们在很多情况下非常相似,但是,两者之间仍然存在一些差异,promises 是将以 asynchronous
方式解决的值,如 HTTP 调用。另一方面,可观察对象处理一系列 异步事件 。它们之间的主要区别如下:
承诺:
- 有一个管道
- 通常只与异步数据一起使用return
- 不容易取消
可观察:
- 可取消
- 本质上是可重试的,例如 retry 和 retryWhen
- 在多个管道中流式传输数据
- 具有类似数组的操作,如映射、过滤器等
- 可以从事件等其他来源创建
- 它们是函数,稍后可以订阅
此外,我在下面为您创建了图形图像,以直观地显示差异:
我相信所有其他答案都应该消除您的疑虑。
不过,我只是想补充一点,可观察对象是基于函数式编程的,我发现它附带的函数非常有用,比如 map、flatmap、reduce、zip。 Web 实现的一致性,尤其是当它依赖于 API 请求时,是一个残酷的改进。
我强烈推荐 this documentation,因为它是 reactiveX 的官方文档,我发现它是最清晰的。
如果你想了解 observables,我会建议这个 3 部分 post:
http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/
虽然它是针对 RxJava 的,但概念是相同的,而且解释得非常好。在 reactiveX 文档中,每个函数都有等效项。你必须寻找 RxJS。
答案中缺少 Observables 的一个缺点。 Promises 允许使用 ES7 async/await 函数。使用它们,您可以编写异步代码,就像同步函数调用一样,因此您不再需要回调。 Observables 做到这一点的唯一可能性是将它们转换为 Promises。但是当你将它们转换为 Promises 时,你只能再次拥有一个 return 值:
async function getData(){
const data = await observable.first().toPromise();
//do stuff with 'data' (no callback function needed)
}
进一步阅读:
承诺:
- 提供单一未来价值;
- 不懒惰;
- 不可取消;
可观察:
- 随时间发出多个值;
- 懒惰;
- 可取消;
- 支持 map、filter、reduce 和类似的运算符
如果您愿意,可以在 Angular 中调用 HTTP 时使用 promises 而不是 observables。
我总结了下面的差异,
可观测:
- Observable 只是一个
function
需要 an observer
和 returns 一个 function Observer: an object with next, error.
- 观察者允许
subscribe/unsubscribe
到它的数据流,发出
观察者的下一个值,notify
观察者关于 errors
和
通知观察者 stream completion
- 观察者提供了一个
function to handle next value
,错误和
流结束(UI 事件、http 响应、带有网络套接字的数据)。
- 随着时间的推移与
multiple values
一起工作
- 即
cancel-able/retry-able
,支持map, filter, reduce
等运算符
- 创建一个 Observable 可以是
-
Observable.create()
- returns 可以调用方法的 Observable
-Observer Observable.from()
- 将数组或可迭代对象转换为
-Observable Observable.fromEvent()
- 将事件转换为 Observable
-Observable.fromPromise()
- 将 Promise 转换为 Observable
-Observable.range()
- returns指定范围内的整数序列
承诺:
一个promise代表一个将在未来完成的任务;
承诺变成resolved by a value
;
承诺被异常拒绝;
不是cancellable
而是returnsa single value
一个承诺公开一个函数(then)
-然后 returns 一个新的 promise
;
-允许 attachment
将基于
state
;
-handlers
是guaranteed
在order attached
执行;
Promises 和 Observables 都只处理异步调用。
以下是它们之间的区别:
可观察
- 在一段时间内发出多个值
- 在我们订阅 Observable 之前不会被调用
- 可以使用unsubscribe()方法取消
- 提供 map、forEach、filter、reduce、retry 和 retryWhen 运算符
承诺
一次只发出一个值
调用不带 .then 和 .catch 的服务
无法取消
不提供任何运算符
Promise - 提供单一的未来价值。不懒惰。不是 cancel-able。它将拒绝或解决。
Observable - 提供多个未来值。懒惰的。 Cancel-able。它提供了其他方法,如 map、filter 和 reduce.
这个话题已经有很多答案了,我就不多说了。
但是对于刚开始学习 Observable / Angular 并且想知道使用哪个与 Promise,我建议你保留所有 Observable 并将项目中所有现有的 Promise 转换为 Observable。
仅仅是因为 Angular 框架本身及其社区都在使用 Observable。因此,当您集成框架服务或第三方模块并将所有内容链接在一起时,这将是有益的。
当然,没有意见在所有情况下都是 100% 正确的,但至少我认为,对于在 Angular 框架中实施的常规商业项目,98% 的时间,Observable 是正确的选择。
即使您在开始简单的爱好项目时不喜欢它,您很快就会意识到在 Angular 中与您交互的几乎所有组件,以及大多数 Angular - 友好的第三方框架正在使用 Observables,然后你最终会不断地将你的 Promise 转换为 Observable 以便与它们通信。
这些组件包括但不限于:HttpClient、表单生成器、Angular material modules/dialogs、Ngrx store/effects 和 ngx-bootstrap.
事实上,我在过去两年中处理的来自 Angular 生态系统的唯一 Promise 是 APP_INITIALIZER
。
概述:
- Promises 和 Observables 都可以帮助我们处理异步操作。当这些异步操作完成时,他们可以调用某些回调。
- 一个 Promise 只能处理一个事件,Observables 用于随时间变化的事件流
- 承诺一旦挂起就无法取消
- Observables 发出的数据可以使用运算符进行转换
您始终可以使用可观察对象来处理异步行为,因为可观察对象具有承诺提供的所有功能(+ 额外)。然而,有时不需要 Observables 提供的这种额外功能。然后导入一个库来使用它们会是额外的开销。
何时使用 Promises:
当您有一个 单个 异步操作要处理其结果时,请使用 promises。例如:
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
因此,promise 在解析或拒绝时执行一些代码。如果 resolve 或 reject 被调用,promise 从 pending 状态 变为 resolved 或 rejected状态。当 promise 状态被解析时, then()
方法被调用。当promise状态被拒绝时,调用catch()
方法
何时使用 Observables:
当有 随时间变化的(数据)流 需要处理时,使用 Observables。流是随时间可用的数据元素序列。流的例子是:
- 用户事件,例如单击,或 keyup 事件。用户随时间生成事件(数据)。
- Websockets,在客户端与服务器建立 WebSocket 连接后,它会随着时间的推移推送数据。
当下一个事件发生时,当错误发生时,或者当Observable是[=35]时,Observable本身被指定=]完成。然后我们可以订阅这个 observable,它会激活它,在这个订阅中,我们可以传入 3 个回调(不必总是传入所有回调)。一种是成功回调,一种是错误回调,一种是完成回调。例如:
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
当创建一个可观察对象时,它需要一个回调函数,该函数提供一个观察者作为参数。在这个观察者上,您可以调用 onNext
、onCompleted
、onError
。然后当 Observable 被订阅时,它会调用传递给订阅的相应回调。
简答:
Observable 更好。它具有所有 Promises 功能以及额外功能。
长答案:
承诺:
- 一次性使用“Return数据一次”
- 不取消
- 一位听众
- 不支持套接字
观察值:
- Return数据多次变化
- 支持取消
- 支持插座
- 支持多个侦听器并在数据更改时通知他们
- 支持映射、过滤和归约
Below are some important differences in promises & Observables.
承诺
- 仅发出单个值
- 不可取消
- 不可分享
- 始终异步
可观察
- 发出多个值
- 仅在调用或有人订阅时执行
- 可以取消
- 可以由多个订阅者共享和订阅该共享值。所有订阅者都将在一个时间点执行。
- 可能是异步的
为了更好地理解,请参阅 https://stackblitz.com/edit/observable-vs-promises
虽然 总体上很好,但我不认为它强调在处理 Angular 组件时你几乎总是想使用 Observable,因为它支持取消。 Promises 无法取消,即使您的组件被销毁也会解决。 Angular 倾向于宽容,直到不再宽容。
例如,对已销毁组件的任何手动更改检测都会导致异常:
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();
});
}
如果您的组件在 promise 解析之前被销毁,您将在 promise 解析时收到 attempt to use destroyed view
错误。
或者,如果您使用具有 模式的可观察对象,那么一旦您的组件被销毁,订阅就会被取消。
这是一个有点人为的例子,但是为一个被破坏的组件执行代码可能会导致错误。
Observables 和 Promises 正在帮助我们使用 JavaScript/TypeScript 中的异步功能。它们在很多情况下非常相似,但是它们之间仍然存在一些差异。
我 运行 在第一次阅读本教程和文档时并未发现的一点是多播的概念。
确保您知道默认情况下,多个订阅将触发 Observable 中的多个执行。对单个 HTTP 调用 Observable 的多个订阅将触发多个相同的 HTTP 调用,除非您 .share()
(启用多播)。
Promise 迫使您一次处理一件事,解包数据,处理异常,对 async/await 等很酷的事情有语言支持,否则就很简单。
Observable 有很多花里胡哨的功能,但您需要了解您正在使用的功能,否则它可能会被滥用。
承诺:
异步事件处理程序 - Promise 对象表示异步操作的最终完成(或失败)及其结果值。
语法: new Promise(executor);
例如:
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);
关于承诺:
它只有一个管道,所以它只会在调用时 return 值一次。
它是一种单向处理程序,因此一旦调用您可能无法取消。
您可以使用的有用语法,when() 和 then().
观察值:
Observables 是随时间变化的多个值的惰性集合。这确实是异步操作的好方法。可以使用具有跨平台支持的 rxjs 来完成,可以与 Angular/React 等一起使用
它的作用类似于流水线,可以是多流水线。
所以一旦定义,你可以在很多地方订阅得到return结果。
语法: import * as Rx from "@reactivex/rxjs";
初始化:
Rx.Observable.fromEvent(button, "click"),
Rx.Subject()
等等
订阅:RxLogger.getInstance();
例如:
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));
由于它支持多管道,您可以在不同的位置订阅结果,
它有比承诺更多的可能性。
用法:
它有更多的可能性,比如map、filter、pipe、map, concatMap, 等等
我看到很多人使用 Observable 是 "cancellable" 的论点,但是做出 Promise "cancellable"
是相当微不足道的
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
可观察和承诺之间的基本区别是:
Both Promises and Observables help us dealing with asynchronous
operations. They can call certain callbacks when these asynchronous
operations are done.
Angular uses Observables which is from RxJS instead of promises for dealing with HTTP
Below are some important differences in promises & Observables.
Promise 与 Observable 的相似性优先
两者都用于处理异步代码。
请查找承诺示例。 promise 构造函数传递一个 resolve 引用函数,当它在某些异步任务完成时被调用并带有某个值时将被调用。
const promise = new Promise(resolve => {
setTimeout(() => {
resolve("Hello from a Promise!");
}, 2000);
});
promise.then(value => console.log(value));
现在可以观察到的例子。这里我们还传递了一个函数给 observable——一个处理异步任务的观察者。与 promise 中的 resolve 不同的是,它有以下方法并用 subscribes 代替 then。
所以两者都处理异步任务。现在让我们看看区别。
const observable = new Observable(observer => {
setTimeout(() => {
observer.next('Hello from a Observable!');
}, 2000);
});
observable.subscribe(value => console.log(value));
承诺与可观察到的差异
承诺
- 解析或拒绝单值,一次可以处理单值异步任务。
- 一个承诺一旦解决了它完成的异步值,就不能再used.its只是one-time使用,这里它不够用。
- 不可取消
- 不支持 rxjs 运算符。
可观察
能够发出多个异步值。
用于处理事件流或值流。假设您有许多任务或值的数组,并且您希望每次将值插入其中时都应该自动处理。任何时候你将一个值压入这个数组,它的所有订阅者都会自动收到最新的值。
Observable 可用于观察输入变化、重复间隔、向所有子组件广播值、Web 套接字推送通知等
可以随时使用退订方法取消。
承诺的最后一个好部分是支持 rxjs 运算符。您有许多管道运算符,主要是 map、filter、switchMap、combineLatest 等,用于在订阅之前转换可观察数据。
当异步 activity 完成或失败时,Promise 会发出一个事件。
Observable 类似于 Stream(在许多语言中)并允许传递至少零个或多个事件,其中每个事件都需要回调。
Frequently Observable 优于 Promise,因为它提供了 Promise 的亮点等。使用 Observable,无论您需要处理 0、1 还是各种事件都没有关系。您可以对每种情况使用类似的 API。
承诺:
承诺发出单个值
例如:
const numberPromise = new Promise((resolve) => {
resolve(5);
resolve(10);
});
numberPromise.then(value => console.log(value));
// still prints only 5
可观察:
在一段时间内发出多个值
例如:
const numberObservable = new Observable((observer) => {
observer.next(5);
observer.next(10);
});
numberObservable.subscribe(value => console.log(value));
// prints 5 and 10
我们可以将 observable 想象成一个流,它在一段时间内发出多个值,并且为发出的每个项目调用相同的回调函数,因此对于一个 observable,我们可以使用相同的 API 来处理异步数据。该数据是在一段时间内作为单个值还是多个值传输。
承诺:
- 诺言不懒惰
- Promise 无法取消
可观察:
- Observable 是惰性的。 "Observable" 很慢。直到
我们订阅了它。
- 可以使用 unsubscribe() 方法取消 Observable
- 一个额外的 Observable 提供了很多强大的操作符,比如 map,
foreach, filter, reduce, retry, retryWhen 等
- Promise 是急切的,而 Observable 是惰性的。
- Promise 始终是异步的,而 Observable 可以是
同步或异步。
- Promise 可以提供单个值,而 Observable 是一个
值流(从 0 到多个值)。
- 您可以将 RxJS 运算符应用于 Observable 以获得新的定制
流。
Promise 发出单个值,而 Observable 发出多个值。因此,在处理 HTTP 请求时,Promise 可以管理同一请求的单个响应,但是如果对同一请求有多个响应,那么我们必须使用 Observable。是的,Observable 可以处理同一个请求的多个响应。
承诺
const promise = new Promise((data) =>
{ data(1);
data(2);
data(3); })
.then(element => console.log(‘Promise ‘ + element));
输出
Promise 1
可观察
const observable = new Observable((data) => {
data.next(1);
data.next(2);
data.next(3);
}).subscribe(element => console.log('Observable ' + element));
输出
Observable 1
Observable 2
Observable 3
承诺仅针对单个值或解决方案。 Observable 是数据流。
Observable 可以取消,但 promises 不能取消。
最不为人知的一个,至少对我来说是:
- Promise 总是异步的,但 observable 既可以是同步的也可以是异步的。
如果您想详细了解它,我在这个答案之后写了一篇博客 post - The 4 differences between Observables and Promises in JavaScript
Promise:是处理异步代码的 ES6 特性,它在创建时立即执行,当时只能发出一个值并且不可取消。随着现代应用程序和功能需求的复杂性,有必要实现复杂的代码,如果我们正在处理同时执行许多承诺,或在执行前进行过滤或进行一些转换:
myPromise.then((resolvedValue) => {
console.log(resolvedValue);
}, (error) => {
console.log(error);
});
Observable: 是 Rxjs 库提供的一个对象,可以帮助我们在 JavaScript 应用程序中进行响应式编程,它提供链接和订阅来处理复杂的应用程序具有可取消的优点,同时提供许多值。此外,我们可以从应用其他运算符的链接中受益,例如 retry()
、map()
、 filter()
、switchMap()
等有助于处理复杂的用例和繁重的用户界面。
即时搜索示例:
search(terms: Observable<string>) {
return terms.pipe(
debounceTime(400),
distinctUntilChanged(),
switchMap((term) => this.searchEntries(term))
);
}
多个 APIS 并行调用示例:
let character = this.http.get('https://jsonplaceholder.typicode.com/todos');
let characterHomeworld = this.http.get(
'https://jsonplaceholder.typicode.com/posts'
);
forkJoin([character, characterHomeworld]).subscribe((results) => {
console.log('result °', results[0]);
console.log('result 1', results[1]);
});
还有一个区别:全球与进口
承诺是 standard built-in object, and you can use it directly. Check the browser support here。
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ready with out any installation');
}, 300);
});
myPromise
.then(value => { console.log(value) })
.catch(err => { console.log(err) });
可观察,Reactive Extensions for JavaScript need RxJS installation & import 使用前
import { Observable } from 'rxjs';
假设您想去海滩。你必须根据天气做出决定。你有三种方式:
你看看外面,看到雨滴,所以你改变了主意。这是一个同步操作。你停下手头的事情,去外面看看,得到结果,然后又回到你正在做的事情。
你让旁边的弟弟查一下今天的天气情况。当他查看天气时,您仍然继续做您正在做的事情。这是一个异步操作。您将任务交给了您的兄弟,并等待承诺得到解决。在这种情况下,您会收到一个回复,在您收到回复后,您将不再收到任何更新。
这一次,您打开收音机并收听全天候 24/7 广播天气状况的天气频道。在这种情况下,响应是持续的,而不是得到一个单一的响应。此响应类似于 subscription
到 observable
。可观察的是“天气”,订阅是“让您了解最新情况的无线电信号”。只要您的收音机开着,您就会获得所有可用的更新。在您关闭收音机之前,您不会错过任何信息。当您关闭收音机时,表示“您已取消订阅”。
Promise 在异步操作完成或失败时处理单个事件。
Promises 在应用程序中自动执行,而 observables 是惰性的。所以我们必须订阅 observables 以 return 数据。
我们无法取消订阅承诺。与可以取消订阅的 Observables 相比,它们每次都会执行。
Promise 始终是异步的,而 Observable 可以是同步的也可以是异步的。
Observables return 数据随着数据变化多次。
Promise 发出单个值。
Observables 是随时间变化的多个值的惰性集合。这确实是异步操作的好方法。
承诺并不懒惰。
可以使用 unsubscribe() 取消 Observable。
承诺无法取消。
Promise
和Angular中的Observable
有什么区别?
每一个例子都有助于理解这两种情况。每个case可以在什么场景下使用?
承诺
A Promise
在异步操作完成或失败时处理 单个事件。
注意:有 Promise
库支持取消,但 ES6 Promise
目前还不支持。
可观察
Observable
类似于 Stream
(在许多语言中)并允许传递零个或多个事件,其中为每个事件调用回调.
通常 Observable
优于 Promise
,因为它提供了 Promise
的功能以及更多。使用 Observable
时,无论您要处理 0、1 还是多个事件都无关紧要。您可以在每种情况下使用相同的 API。
Observable
也比 Promise
有优势 可取消 。如果不再需要对服务器的 HTTP 请求或其他一些昂贵的异步操作的结果,Observable
的 Subscription
允许取消订阅,而 Promise
最终会即使您不再需要通知或它提供的结果,也可以调用成功或失败的回调。
Promise
会立即启动,而 Observable
只有在您订阅后才会启动。这就是 Observable 被称为惰性的原因。
Observable 提供 operators 像 map
, forEach
, reduce
, ... 类似于数组
还有一些强大的运算符,例如 retry()
或 replay()
,...通常非常方便。
A list of operators shipped with rxjs
惰性执行允许在通过订阅执行可观察对象之前建立一个运算符链,以进行更具声明性的编程。
Promises
和 Observables
都为我们提供了抽象,帮助我们处理应用程序的 异步 性质。
既然一个代码片段抵得上一千个单词,让我们通过下面的例子来更容易地理解它们。
Thanks @Christoph Burgdorf for the awesome article
Angular 使用 Rx.js Observables 而不是 promises 来处理 HTTP。
假设您正在构建一个搜索功能,它会在您键入时立即显示结果。这听起来很熟悉,但这项任务伴随着很多挑战。
- 我们不想在用户每次按键时都访问服务器端点。它应该用 HTTP 请求的风暴淹没他们。基本上,我们只想在用户停止输入而不是每次击键时点击它。
- 不要为后续请求使用相同的查询参数命中搜索端点。
- 处理乱序响应。当我们同时有多个请求在进行中时,我们必须考虑到它们以意想不到的顺序返回的情况。想象一下,我们首先键入 computer,停止,一个请求发出,我们键入 car,停止,一个请求发出。现在我们有两个正在处理的请求。不幸的是,携带 computer 结果的请求在携带 car. 结果的请求之后返回
该演示仅包含两个文件: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>>
作为我们搜索方法的 return 类型结束。
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 returns 的搜索方法,并将其作为简单的字符串数组公开给模板,以便我们可以让 *ngFor
循环遍历它并为我们建立一个列表。
请参阅 基于 Promise 实施的示例 Plunker
Observables 真正闪耀的地方
让我们更改我们的代码,使其不再在每次击键时敲击端点,而是仅在用户停止输入 400 毫秒
时才发送请求要揭示这种超能力,我们首先需要获得一个 Observable<string>
来携带用户输入的搜索词。我们可以利用 [=140 代替手动绑定到 keyup 事件=] 的 formControl
指令。要使用此指令,我们首先需要将 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 自动将 Observable<string>
暴露为 属性 valueChanges
我们可以订阅。现在我们有了 Observable<string>
,克服用户输入就像在我们的 Observable
上调用 debounceTime(400)
一样简单。这将 return 一个新的 Observable<string>
只有在 400 毫秒内没有新值出现时才会发出一个新值。
export class App {
items: Array<string>;
term = new FormControl();
constructor(private wikipediaService: WikipediaService) {
this.term.valueChanges
.debounceTime(400) // wait for 400 ms 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 在 Plunker
上的实施示例For dealing with out-of-order responses, please check the full article http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html
就我在 Angular 中使用 HTTP 而言,我同意在正常用例中使用 Observable 而不是 Promise 没有太大区别。 None 的优点在实践中非常重要。我希望将来能看到一些高级用例:)
Learn more
承诺
- 定义:帮助您 运行 异步运行,并使用它们的 return 值(或异常),但 仅执行一次。
- 不懒惰
- 不可取消(那里有支持取消的 Promise 库,但 ES6 Promise 目前还不支持)。两个可能的决定是
- 拒绝
- 解决
- 不能重试(Promise 应该可以访问 return 承诺具有重试能力的原始函数,这是一种不好的做法)
Observables
- 定义:帮助您运行异步运行,并在执行时以连续序列(多次)使用它们的return值。
- 默认情况下,它是 lazy,因为它会随着时间的推移发出值。
- 有很多运算符,简化了编码工作。
- 一个运算符retry可用于在需要时重试,如果我们需要根据某些条件重试observable,retryWhen也可以被使用。
注意:运算符列表及其交互图可在此处获得 **RxMarbles.com**
我刚刚处理了一个问题,其中 Promises 是最好的解决方案,如果它有用(这正是我之前寻找的答案),我将在这里分享给任何偶然发现这个问题的人:
在 Angular2 项目中,我有一个服务接受一些参数和 returns 一个值列表来填充表单上的下拉菜单。当表单组件初始化时,我需要使用不同的参数多次调用同一个服务来定义多个不同的下拉菜单,但是如果我简单地排队所有变量来调用服务,只有最后一个成功,其余错误出去。从数据库中获取的服务一次只能处理一个请求。
成功填充所有下拉菜单变量的唯一方法是以一种阻止处理新请求的方式调用服务,直到最后一个请求完成,Promise / .then 机制很好地解决了这个问题.
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;
}) }
我在组件中定义了函数,然后在ngOnInit中调用了initializeDropDowns()。
fetchValueList 函数 return 是一个 Promise,因此第一次调用传递了第一个 listCode,当 Promise 解析时,return 值位于 .then 块中的数据变量中,我们可以在其中将其分配给 this.firstValList 变量。由于函数有 returned 数据,我们知道服务已经完成,可以安全地使用第二个 listCode 再次调用,return 值在下一个 .then 块的数据变量中,我们分配它到 this.secondValList 变量。
我们可以根据需要多次链接它以填充所有变量,在最后一个代码块上我们只需省略 return 语句并且块终止。
这是一个非常具体的用例,其中我们有一个服务需要在组件初始化时多次调用,并且该服务必须先完成其获取和 return 一个值才能完成再次调用,但在这种情况下,Promise / .then 方法是理想的。
Promises 和 Observables 都将帮助我们使用 异步功能 JavaScript。它们在很多情况下非常相似,但是,两者之间仍然存在一些差异,promises 是将以 asynchronous
方式解决的值,如 HTTP 调用。另一方面,可观察对象处理一系列 异步事件 。它们之间的主要区别如下:
承诺:
- 有一个管道
- 通常只与异步数据一起使用return
- 不容易取消
可观察:
- 可取消
- 本质上是可重试的,例如 retry 和 retryWhen
- 在多个管道中流式传输数据
- 具有类似数组的操作,如映射、过滤器等
- 可以从事件等其他来源创建
- 它们是函数,稍后可以订阅
此外,我在下面为您创建了图形图像,以直观地显示差异:
我相信所有其他答案都应该消除您的疑虑。 不过,我只是想补充一点,可观察对象是基于函数式编程的,我发现它附带的函数非常有用,比如 map、flatmap、reduce、zip。 Web 实现的一致性,尤其是当它依赖于 API 请求时,是一个残酷的改进。
我强烈推荐 this documentation,因为它是 reactiveX 的官方文档,我发现它是最清晰的。
如果你想了解 observables,我会建议这个 3 部分 post: http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/
虽然它是针对 RxJava 的,但概念是相同的,而且解释得非常好。在 reactiveX 文档中,每个函数都有等效项。你必须寻找 RxJS。
答案中缺少 Observables 的一个缺点。 Promises 允许使用 ES7 async/await 函数。使用它们,您可以编写异步代码,就像同步函数调用一样,因此您不再需要回调。 Observables 做到这一点的唯一可能性是将它们转换为 Promises。但是当你将它们转换为 Promises 时,你只能再次拥有一个 return 值:
async function getData(){
const data = await observable.first().toPromise();
//do stuff with 'data' (no callback function needed)
}
进一步阅读:
承诺:
- 提供单一未来价值;
- 不懒惰;
- 不可取消;
可观察:
- 随时间发出多个值;
- 懒惰;
- 可取消;
- 支持 map、filter、reduce 和类似的运算符
如果您愿意,可以在 Angular 中调用 HTTP 时使用 promises 而不是 observables。
我总结了下面的差异,
可观测:
- Observable 只是一个
function
需要an observer
和 returns 一个function Observer: an object with next, error.
- 观察者允许
subscribe/unsubscribe
到它的数据流,发出 观察者的下一个值,notify
观察者关于errors
和 通知观察者stream completion
- 观察者提供了一个
function to handle next value
,错误和 流结束(UI 事件、http 响应、带有网络套接字的数据)。 - 随着时间的推移与
multiple values
一起工作 - 即
cancel-able/retry-able
,支持map, filter, reduce
等运算符 - 创建一个 Observable 可以是
-
Observable.create()
- returns 可以调用方法的 Observable -Observer Observable.from()
- 将数组或可迭代对象转换为 -Observable Observable.fromEvent()
- 将事件转换为 Observable -Observable.fromPromise()
- 将 Promise 转换为 Observable -Observable.range()
- returns指定范围内的整数序列
承诺:
一个promise代表一个将在未来完成的任务;
承诺变成
resolved by a value
;承诺被异常拒绝;
不是
cancellable
而是returnsa single value
一个承诺公开一个函数
(then)
-然后 returns 一个新的
promise
;-允许
attachment
将基于state
;-
handlers
是guaranteed
在order attached
执行;
Promises 和 Observables 都只处理异步调用。
以下是它们之间的区别:
可观察
- 在一段时间内发出多个值
- 在我们订阅 Observable 之前不会被调用
- 可以使用unsubscribe()方法取消
- 提供 map、forEach、filter、reduce、retry 和 retryWhen 运算符
承诺
一次只发出一个值
调用不带 .then 和 .catch 的服务
无法取消
不提供任何运算符
Promise - 提供单一的未来价值。不懒惰。不是 cancel-able。它将拒绝或解决。
Observable - 提供多个未来值。懒惰的。 Cancel-able。它提供了其他方法,如 map、filter 和 reduce.
这个话题已经有很多答案了,我就不多说了。
但是对于刚开始学习 Observable / Angular 并且想知道使用哪个与 Promise,我建议你保留所有 Observable 并将项目中所有现有的 Promise 转换为 Observable。
仅仅是因为 Angular 框架本身及其社区都在使用 Observable。因此,当您集成框架服务或第三方模块并将所有内容链接在一起时,这将是有益的。
当然,没有意见在所有情况下都是 100% 正确的,但至少我认为,对于在 Angular 框架中实施的常规商业项目,98% 的时间,Observable 是正确的选择。
即使您在开始简单的爱好项目时不喜欢它,您很快就会意识到在 Angular 中与您交互的几乎所有组件,以及大多数 Angular - 友好的第三方框架正在使用 Observables,然后你最终会不断地将你的 Promise 转换为 Observable 以便与它们通信。
这些组件包括但不限于:HttpClient、表单生成器、Angular material modules/dialogs、Ngrx store/effects 和 ngx-bootstrap.
事实上,我在过去两年中处理的来自 Angular 生态系统的唯一 Promise 是 APP_INITIALIZER
。
概述:
- Promises 和 Observables 都可以帮助我们处理异步操作。当这些异步操作完成时,他们可以调用某些回调。
- 一个 Promise 只能处理一个事件,Observables 用于随时间变化的事件流
- 承诺一旦挂起就无法取消
- Observables 发出的数据可以使用运算符进行转换
您始终可以使用可观察对象来处理异步行为,因为可观察对象具有承诺提供的所有功能(+ 额外)。然而,有时不需要 Observables 提供的这种额外功能。然后导入一个库来使用它们会是额外的开销。
何时使用 Promises:
当您有一个 单个 异步操作要处理其结果时,请使用 promises。例如:
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
因此,promise 在解析或拒绝时执行一些代码。如果 resolve 或 reject 被调用,promise 从 pending 状态 变为 resolved 或 rejected状态。当 promise 状态被解析时, then()
方法被调用。当promise状态被拒绝时,调用catch()
方法
何时使用 Observables:
当有 随时间变化的(数据)流 需要处理时,使用 Observables。流是随时间可用的数据元素序列。流的例子是:
- 用户事件,例如单击,或 keyup 事件。用户随时间生成事件(数据)。
- Websockets,在客户端与服务器建立 WebSocket 连接后,它会随着时间的推移推送数据。
当下一个事件发生时,当错误发生时,或者当Observable是[=35]时,Observable本身被指定=]完成。然后我们可以订阅这个 observable,它会激活它,在这个订阅中,我们可以传入 3 个回调(不必总是传入所有回调)。一种是成功回调,一种是错误回调,一种是完成回调。例如:
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
当创建一个可观察对象时,它需要一个回调函数,该函数提供一个观察者作为参数。在这个观察者上,您可以调用 onNext
、onCompleted
、onError
。然后当 Observable 被订阅时,它会调用传递给订阅的相应回调。
简答:
Observable 更好。它具有所有 Promises 功能以及额外功能。
长答案:
承诺:
- 一次性使用“Return数据一次”
- 不取消
- 一位听众
- 不支持套接字
观察值:
- Return数据多次变化
- 支持取消
- 支持插座
- 支持多个侦听器并在数据更改时通知他们
- 支持映射、过滤和归约
Below are some important differences in promises & Observables.
承诺
- 仅发出单个值
- 不可取消
- 不可分享
- 始终异步
可观察
- 发出多个值
- 仅在调用或有人订阅时执行
- 可以取消
- 可以由多个订阅者共享和订阅该共享值。所有订阅者都将在一个时间点执行。
- 可能是异步的
为了更好地理解,请参阅 https://stackblitz.com/edit/observable-vs-promises
虽然
例如,对已销毁组件的任何手动更改检测都会导致异常:
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();
});
}
如果您的组件在 promise 解析之前被销毁,您将在 promise 解析时收到 attempt to use destroyed view
错误。
或者,如果您使用具有
这是一个有点人为的例子,但是为一个被破坏的组件执行代码可能会导致错误。
Observables 和 Promises 正在帮助我们使用 JavaScript/TypeScript 中的异步功能。它们在很多情况下非常相似,但是它们之间仍然存在一些差异。
我 运行 在第一次阅读本教程和文档时并未发现的一点是多播的概念。
确保您知道默认情况下,多个订阅将触发 Observable 中的多个执行。对单个 HTTP 调用 Observable 的多个订阅将触发多个相同的 HTTP 调用,除非您 .share()
(启用多播)。
Promise 迫使您一次处理一件事,解包数据,处理异常,对 async/await 等很酷的事情有语言支持,否则就很简单。
Observable 有很多花里胡哨的功能,但您需要了解您正在使用的功能,否则它可能会被滥用。
承诺:
异步事件处理程序 - Promise 对象表示异步操作的最终完成(或失败)及其结果值。
语法: new Promise(executor);
例如:
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);
关于承诺:
它只有一个管道,所以它只会在调用时 return 值一次。 它是一种单向处理程序,因此一旦调用您可能无法取消。 您可以使用的有用语法,when() 和 then().
观察值:
Observables 是随时间变化的多个值的惰性集合。这确实是异步操作的好方法。可以使用具有跨平台支持的 rxjs 来完成,可以与 Angular/React 等一起使用
它的作用类似于流水线,可以是多流水线。 所以一旦定义,你可以在很多地方订阅得到return结果。
语法: import * as Rx from "@reactivex/rxjs";
初始化:
Rx.Observable.fromEvent(button, "click"),
Rx.Subject()
等等
订阅:RxLogger.getInstance();
例如:
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));
由于它支持多管道,您可以在不同的位置订阅结果,
它有比承诺更多的可能性。
用法:
它有更多的可能性,比如map、filter、pipe、map, concatMap, 等等
我看到很多人使用 Observable 是 "cancellable" 的论点,但是做出 Promise "cancellable"
是相当微不足道的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
可观察和承诺之间的基本区别是:
Both Promises and Observables help us dealing with asynchronous operations. They can call certain callbacks when these asynchronous operations are done.
Angular uses Observables which is from RxJS instead of promises for dealing with HTTP
Below are some important differences in promises & Observables.
Promise 与 Observable 的相似性优先
两者都用于处理异步代码。
请查找承诺示例。 promise 构造函数传递一个 resolve 引用函数,当它在某些异步任务完成时被调用并带有某个值时将被调用。
const promise = new Promise(resolve => { setTimeout(() => { resolve("Hello from a Promise!"); }, 2000); }); promise.then(value => console.log(value));
现在可以观察到的例子。这里我们还传递了一个函数给 observable——一个处理异步任务的观察者。与 promise 中的 resolve 不同的是,它有以下方法并用 subscribes 代替 then。
所以两者都处理异步任务。现在让我们看看区别。
const observable = new Observable(observer => { setTimeout(() => { observer.next('Hello from a Observable!'); }, 2000); }); observable.subscribe(value => console.log(value));
承诺与可观察到的差异
承诺
- 解析或拒绝单值,一次可以处理单值异步任务。
- 一个承诺一旦解决了它完成的异步值,就不能再used.its只是one-time使用,这里它不够用。
- 不可取消
- 不支持 rxjs 运算符。
可观察
能够发出多个异步值。
用于处理事件流或值流。假设您有许多任务或值的数组,并且您希望每次将值插入其中时都应该自动处理。任何时候你将一个值压入这个数组,它的所有订阅者都会自动收到最新的值。
Observable 可用于观察输入变化、重复间隔、向所有子组件广播值、Web 套接字推送通知等
可以随时使用退订方法取消。
承诺的最后一个好部分是支持 rxjs 运算符。您有许多管道运算符,主要是 map、filter、switchMap、combineLatest 等,用于在订阅之前转换可观察数据。
当异步 activity 完成或失败时,Promise 会发出一个事件。
Observable 类似于 Stream(在许多语言中)并允许传递至少零个或多个事件,其中每个事件都需要回调。
Frequently Observable 优于 Promise,因为它提供了 Promise 的亮点等。使用 Observable,无论您需要处理 0、1 还是各种事件都没有关系。您可以对每种情况使用类似的 API。
承诺: 承诺发出单个值
例如:
const numberPromise = new Promise((resolve) => {
resolve(5);
resolve(10);
});
numberPromise.then(value => console.log(value));
// still prints only 5
可观察: 在一段时间内发出多个值
例如:
const numberObservable = new Observable((observer) => {
observer.next(5);
observer.next(10);
});
numberObservable.subscribe(value => console.log(value));
// prints 5 and 10
我们可以将 observable 想象成一个流,它在一段时间内发出多个值,并且为发出的每个项目调用相同的回调函数,因此对于一个 observable,我们可以使用相同的 API 来处理异步数据。该数据是在一段时间内作为单个值还是多个值传输。
承诺:
- 诺言不懒惰
- Promise 无法取消
可观察:
- Observable 是惰性的。 "Observable" 很慢。直到 我们订阅了它。
- 可以使用 unsubscribe() 方法取消 Observable
- 一个额外的 Observable 提供了很多强大的操作符,比如 map, foreach, filter, reduce, retry, retryWhen 等
- Promise 是急切的,而 Observable 是惰性的。
- Promise 始终是异步的,而 Observable 可以是 同步或异步。
- Promise 可以提供单个值,而 Observable 是一个
值流(从 0 到多个值)。 - 您可以将 RxJS 运算符应用于 Observable 以获得新的定制 流。
Promise 发出单个值,而 Observable 发出多个值。因此,在处理 HTTP 请求时,Promise 可以管理同一请求的单个响应,但是如果对同一请求有多个响应,那么我们必须使用 Observable。是的,Observable 可以处理同一个请求的多个响应。
承诺
const promise = new Promise((data) =>
{ data(1);
data(2);
data(3); })
.then(element => console.log(‘Promise ‘ + element));
输出
Promise 1
可观察
const observable = new Observable((data) => {
data.next(1);
data.next(2);
data.next(3);
}).subscribe(element => console.log('Observable ' + element));
输出
Observable 1
Observable 2
Observable 3
承诺仅针对单个值或解决方案。 Observable 是数据流。
Observable 可以取消,但 promises 不能取消。
最不为人知的一个,至少对我来说是:
- Promise 总是异步的,但 observable 既可以是同步的也可以是异步的。
如果您想详细了解它,我在这个答案之后写了一篇博客 post - The 4 differences between Observables and Promises in JavaScript
Promise:是处理异步代码的 ES6 特性,它在创建时立即执行,当时只能发出一个值并且不可取消。随着现代应用程序和功能需求的复杂性,有必要实现复杂的代码,如果我们正在处理同时执行许多承诺,或在执行前进行过滤或进行一些转换:
myPromise.then((resolvedValue) => {
console.log(resolvedValue);
}, (error) => {
console.log(error);
});
Observable: 是 Rxjs 库提供的一个对象,可以帮助我们在 JavaScript 应用程序中进行响应式编程,它提供链接和订阅来处理复杂的应用程序具有可取消的优点,同时提供许多值。此外,我们可以从应用其他运算符的链接中受益,例如 retry()
、map()
、 filter()
、switchMap()
等有助于处理复杂的用例和繁重的用户界面。
即时搜索示例:
search(terms: Observable<string>) {
return terms.pipe(
debounceTime(400),
distinctUntilChanged(),
switchMap((term) => this.searchEntries(term))
);
}
多个 APIS 并行调用示例:
let character = this.http.get('https://jsonplaceholder.typicode.com/todos');
let characterHomeworld = this.http.get(
'https://jsonplaceholder.typicode.com/posts'
);
forkJoin([character, characterHomeworld]).subscribe((results) => {
console.log('result °', results[0]);
console.log('result 1', results[1]);
});
还有一个区别:全球与进口
承诺是 standard built-in object, and you can use it directly. Check the browser support here。
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ready with out any installation');
}, 300);
});
myPromise
.then(value => { console.log(value) })
.catch(err => { console.log(err) });
可观察,Reactive Extensions for JavaScript need RxJS installation & import 使用前
import { Observable } from 'rxjs';
假设您想去海滩。你必须根据天气做出决定。你有三种方式:
你看看外面,看到雨滴,所以你改变了主意。这是一个同步操作。你停下手头的事情,去外面看看,得到结果,然后又回到你正在做的事情。
你让旁边的弟弟查一下今天的天气情况。当他查看天气时,您仍然继续做您正在做的事情。这是一个异步操作。您将任务交给了您的兄弟,并等待承诺得到解决。在这种情况下,您会收到一个回复,在您收到回复后,您将不再收到任何更新。
这一次,您打开收音机并收听全天候 24/7 广播天气状况的天气频道。在这种情况下,响应是持续的,而不是得到一个单一的响应。此响应类似于
subscription
到observable
。可观察的是“天气”,订阅是“让您了解最新情况的无线电信号”。只要您的收音机开着,您就会获得所有可用的更新。在您关闭收音机之前,您不会错过任何信息。当您关闭收音机时,表示“您已取消订阅”。
Promise 在异步操作完成或失败时处理单个事件。
Promises 在应用程序中自动执行,而 observables 是惰性的。所以我们必须订阅 observables 以 return 数据。
我们无法取消订阅承诺。与可以取消订阅的 Observables 相比,它们每次都会执行。
Promise 始终是异步的,而 Observable 可以是同步的也可以是异步的。 Observables return 数据随着数据变化多次。 Promise 发出单个值。 Observables 是随时间变化的多个值的惰性集合。这确实是异步操作的好方法。 承诺并不懒惰。 可以使用 unsubscribe() 取消 Observable。 承诺无法取消。