Roh*_*hit 1291 promise rxjs angular-promise angular angular-observable
有人可以解释Angular Promise和之间的区别Observable吗?
每个例子都有助于理解这两种情况.在什么情况下我们可以使用每个案例?
Gün*_*uer 1449
诺言
当异步操作完成或失败时,A Promise处理单个事件.
注意:那里Promise有支持取消的库,但Promise到目前为止还没有ES6 .
可观察
An Observable类似于Stream(在许多语言中)并允许传递零个或多个事件,其中为每个事件调用回调.
通常Observable是首选,Promise因为它提供了Promise更多的功能.有了Observable它,如果你想处理0,1或多个事件没有关系.您可以在每种情况下使用相同的API.
Observable也有优势Promise要取消.如果不再需要一个HTTP请求到服务器或其他一些昂贵的异步操作的结果是,Subscription一个Observable允许取消订阅,而Promise最终将调用的成功或失败的回调,即使你不需要通知或者它提供的结果.
可观察到的提供运营商等map,forEach,reduce,...相似的阵列
还有一些强大的运营商,比如retry(),或者replay()......通常非常方便.
tru*_*k18 310
双方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]);
}
}
Run Code Online (Sandbox Code Playgroud)
我们正在注入该Jsonp服务,以GET针对具有给定搜索词的Wikipedia API提出请求.请注意,我们打电话toPromise是为了从a Observable<Response>到a Promise<Response>.最终以a 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);
}
}
Run Code Online (Sandbox Code Playgroud)
这里也没有什么惊喜.我们注入WikipediaService并通过搜索方法将其功能暴露给模板.模板只是绑定到keyup和调用search(term.value).
我们打开了Promise的结果,即WikipediaService的搜索方法返回并将其作为一个简单的字符串数组暴露给模板,以便我们可以*ngFor循环遍历它并为我们建立一个列表.
当观测量大放异彩
让我们改变我们的代码,不要在每次击键时敲击端点,而只是在用户停止键入400 ms时才发送请求
为了揭示这样的超能力,我们首先需要得到一个Observable<string>带有用户输入的搜索词.而不是手动绑定到keyup事件,我们可以利用Angular的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 {}
Run Code Online (Sandbox Code Playgroud)
导入后,我们可以在模板中使用formControl并将其设置为名称"term".
<input type="text" [formControl]="term"/>
Run Code Online (Sandbox Code Playgroud)
在我们的组件中,我们创建一个FormControlfrom 的实例,@angular/form并将其作为我们组件上名称term下的字段公开.
在幕后,术语会自动公开我们可以订阅的Observable<string>属性valueChanges.现在我们有了Observable<string>,克服用户输入就像调用debounceTime(400)我们一样简单Observable.这将返回一个新的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));
}
}
Run Code Online (Sandbox Code Playgroud)
发送我们的应用已经显示结果的搜索字词的另一个请求将浪费资源.我们所要做的就是distinctUntilChanged在我们调用之后立即调用操作符debounceTime(400)
要处理无序响应,请查看完整的文章 http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html
至于我在Angular中使用Http,我同意在正常使用情况下使用Observable而不是Promise没有太大区别.在实践中,这些优点都没有真正相关.希望将来可以看到一些高级用例:)
学到更多
Ali*_*eza 214
双方承诺和观测量将有助于我们与合作异步功能在JavaScript中.它们在许多情况下非常相似,但是,两者之间仍然存在一些差异,承诺是将以http调用的asynchronous方式解决的值.另一方面,observable处理一系列异步事件.它们之间的主要区别如下:
诺言:
观察到:
另外,我在下面为您创建了图形图像,以便直观地显示差异:
Ara*_*ind 69
承诺
观测
当需要时,可以使用一个运算符重试来重试,如果我们需要根据某些条件重试observable retryWhen可以使用.
注意:RxMarbles.com提供了运营商列表及其交互式图表
bes*_*ser 62
在答案中缺少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)
}
Run Code Online (Sandbox Code Playgroud)
进一步阅读:如何在Rx Observable上"等待"?
Yil*_*maz 44
假设您想去海滩。您必须根据天气做出决定。你有三种方法:
你向外望去,看到了雨滴,所以你改变了主意。这是一个同步操作。你停下手头的事情,去看看外面,得到结果,然后又回到你正在做的事情。
你让旁边的兄弟查看今天的天气状况。当他查看天气时,你仍然继续做你正在做的事情。这是一个异步操作。你给了你兄弟一个任务并等待承诺得到解决。在这种情况下,您将收到一个回复,在收到回复后,您将不再收到任何更新。
这次,您打开收音机并收听 24/7 广播天气状况的天气频道。在这种情况下,响应不是得到单一响应,而是持续进行。这个响应就像 asubscription到 an observable。可观察的是“天气”,订阅的是“让您了解最新情况的无线电信号”。只要您的收音机打开,您就会收到所有可用的更新。在关闭收音机之前,您不会错过任何信息。当您关闭收音机时,这意味着“您取消订阅”。
sud*_*nna 34
promises和Observable都只处理异步调用.找到上面的图像主要区别.
Saj*_*ran 23
即使这个答案迟了,我总结了下面的差异,
观察到:
function接受an observer并返回一个 function Observer: an object with next, error.subscribe/unsubscribe向其数据流发送下一个值给观察者,notify观察者errors并告知观察者stream completionfunction to handle next value错误和流的结束(ui事件,http响应,带有web套接字的数据).multiple values随着时间的推移cancel-able/retry-able支持等运营商map,filter,reduce.Observable.create()- 返回可以调用方法的Observable Observer Observable.from()- 将数组或者iterable转换为Observable Observable.fromEvent()- 将事件转换为Observable Observable.fromPromise()- 将Promise转换为Observable Observable.range()- 返回指定范围内的整数序列承诺:
承诺代表着将来完成的任务;
承诺成为resolved by a value;
承诺被例外拒绝;
不cancellable,它返回a single value
承诺揭示一个功能 (then)
然后返回一个新的 promise;
- 允许attachment执行的内容将基于
state;
- handlers是 guaranteed执行中order attached;
小智 19
我相信所有其他答案都应该清除你的疑虑.不过,我只是想补充说,observables是基于函数式编程的,我发现它附带的函数非常有用,如map,flatmap,reduce,zip.Web实现的一致性,特别是当它依赖于API请求时,是一种残酷的改进.
我强烈推荐这个文档,因为它是reactiveX的官方文档,我发现它是最明确的.
如果你想进入observables,我会建议这个由3部分组成的帖子:http: //blog.danlew.net/2014/09/15/grokking-rxjava-part-1/
虽然它适用于RxJava,但概念是相同的,并且它的解释非常好.在reactiveX文档中,您具有每个函数的等价性.你必须寻找RxJS.
Ste*_*ith 18
我刚刚处理了一个问题,其中Promises是最好的解决方案,我在这里分享它,因为任何人在这个问题很有用的情况下绊倒这个问题(这正是我之前寻找的答案):
在Angular2项目中,我有一个服务,它接受一些参数并返回一个值列表来填充表单上的下拉菜单.当表单组件初始化时,我需要使用不同的参数多次调用相同的服务来定义许多不同的下拉菜单,但是如果我只是将所有变量排队以调用服务,则只有最后一个成功并且其余错误出.从数据库获取的服务一次只能处理一个请求.
成功填充所有下拉菜单变量的唯一方法是以阻止在上一个请求完成之前处理新请求的方式调用服务,并且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;
}) }
Run Code Online (Sandbox Code Playgroud)
我在组件中定义了函数,然后在ngOnInit中调用了initializeDropDowns().
fetchValueList函数返回一个Promise,因此第一个调用传递第一个listCode,当Promise解析时,返回值位于.then块中的数据变量中,我们可以将它分配给this.firstValList变量.当函数返回数据时,我们知道服务已经完成,并且使用第二个listCode再次调用是安全的,返回值在下一个.then块的数据变量中,我们将它分配给this.secondValList变量.
我们可以根据需要连接多次来填充所有变量,在最后一个代码块中我们只是省略return语句并且块终止.
这是一个非常具体的用例,我们有一个单独的服务需要在组件初始化时多次调用,并且服务必须完成其获取并返回一个值才能再次调用,但在这种情况下, Promise/.then方法很理想.
小智 16
小智 14
Promise 发出单个值,而 Observable 发出多个值。所以,在处理一个 HTTP 请求时,Promise 可以管理同一个请求的单个响应,但是如果同一个请求有多个响应,那么我们必须使用 Observable。是的,Observable 可以处理同一个请求的多个响应。
承诺
const promise = new Promise((data) =>
{ data(1);
data(2);
data(3); })
.then(element => console.log(‘Promise ‘ + element));
Run Code Online (Sandbox Code Playgroud)
输出
Promise 1
Run Code Online (Sandbox Code Playgroud)
可观察的
const observable = new Observable((data) => {
data.next(1);
data.next(2);
data.next(3);
}).subscribe(element => console.log('Observable ' + element));
Run Code Online (Sandbox Code Playgroud)
输出
Observable 1
Observable 2
Observable 3
Run Code Online (Sandbox Code Playgroud)
小智 13
两者都用于处理异步代码。
请寻找承诺的例子。承诺构造函数传递一个解析引用函数,该函数将在某些异步任务完成后被调用时调用。
const promise = new Promise(resolve => {
setTimeout(() => {
resolve("Hello from a Promise!");
}, 2000);
});
promise.then(value => console.log(value));
Run Code Online (Sandbox Code Playgroud)
现在可以观察到的例子。在这里,我们还向 observable 传递了一个函数——一个处理异步任务的观察者。与promise 中的resolve 不同,它具有以下方法并订阅代替then。
所以两者都处理异步任务。现在让我们看看区别。
const observable = new Observable(observer => {
setTimeout(() => {
observer.next('Hello from a Observable!');
}, 2000);
});
observable.subscribe(value => console.log(value));
Run Code Online (Sandbox Code Playgroud)
承诺
可观察的
能够发出多个异步值。
用于处理事件或值流。考虑到您有一个包含大量任务或值的数组,并且您希望每次将值插入其中时都应该自动处理。任何时候你将一个值推入这个数组,它的所有订阅者都会自动收到最新的值。
Observables 可用于观察输入变化、重复间隔、向所有子组件广播值、Web 套接字推送通知等。
可以随时使用退订方法取消。
承诺的最后一个好部分是支持 rxjs 操作符。您有许多管道操作符,主要是 map、filter、switchMap、combineLatest 等,用于在订阅之前转换可观察数据。
Wil*_*een 12
您始终可以使用observable来处理异步行为,因为observable具有promise提供的所有功能(+ extra).但是,有时候不需要Observables提供的这些额外功能.然后为它导入一个库以便使用它们将是额外的开销.
当你有一个使用的承诺 单,其中要处理的结果异步操作.例如:
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
Run Code Online (Sandbox Code Playgroud)
因此,承诺会执行某些代码,无论是解析还是拒绝.如果调用resolve或reject,则promise将从挂起状态变为已解决或拒绝状态.当解析promise状态时,then()调用该方法.当promise状态被拒绝时,catch()调用该方法.
当存在需要处理的数据流(数据)时使用Observable .流是一系列数据元素,随着时间的推移可用.流的示例是:
Observable本身在下一个事件发生时,发生错误时或者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
Run Code Online (Sandbox Code Playgroud)
在创建一个observable时,它需要一个回调函数,它将一个观察者作为参数提供.在此观察,那么你可以打电话onNext,onCompleted,onError.然后,当Observable订阅它时,它将调用传递给订阅的相应回调.
DeC*_*DeC 10
当异步活动完成或失败时,Promise 会发出单个事件。
一个 Observable 就像一个 Stream(在许多语言中)并且允许传递至少零个或多个事件,其中每个事件都需要回调。
与 Promise 相比,Frequently Observable 更受欢迎,因为它提供了 Promise 的亮点等等。使用 Observable,您是否需要处理 0、1 或各种事件并不重要。您可以为每种情况使用类似的 API。
承诺: 承诺发出单个值
例如:
const numberPromise = new Promise((resolve) => {
resolve(5);
resolve(10);
});
numberPromise.then(value => console.log(value));
// still prints only 5
Run Code Online (Sandbox Code Playgroud)
Observable: 在一段时间内发出多个值
例如:
const numberObservable = new Observable((observer) => {
observer.next(5);
observer.next(10);
});
numberObservable.subscribe(value => console.log(value));
// prints 5 and 10
Run Code Online (Sandbox Code Playgroud)
我们可以将 observable 视为在一段时间内发出多个值的流,并且为每个发出的项目调用相同的回调函数,因此对于 observable,我们可以使用相同的 API 来处理异步数据。该数据是作为单个值还是在一段时间内作为多个值传输。
承诺:
可观察:
Promises 和 Observables 都帮助我们处理异步操作。当这些异步操作完成时,它们可以调用某些回调。
Angular 使用来自 RxJS 的 Observables 而不是 promises 来处理 HTTP
Below are some important differences in promises & Observables.
小智 8
小智 7
在第一次阅读教程和文档时,我遇到的一些问题并不明显,那就是多播的概念。
确保您知道默认情况下,多个订阅将触发 Observable 中的多次执行。对单个 HTTP 调用 Observable 的多个订阅将触发多个相同的 HTTP 调用,除非您.share()(启用多播)。
Promise 迫使您一次处理一件事,解开其数据,处理异常,为 async/await 等很酷的事情提供语言支持,否则就非常简单了。
Observable 有很多花里胡哨的功能,但您需要了解您正在使用的功能,否则它可能会被滥用。
以下是 promises 和 Observables 的一些重要区别。
承诺
可观察的
为了更好地理解,请参阅https://stackblitz.com/edit/observable-vs-promises
承诺:
异步事件处理程序 - 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);
Run Code Online (Sandbox Code Playgroud)
关于承诺:
它有一个管道,所以它在被调用时只会返回一次值。这是一种单向处理程序,因此一旦被调用,您可能无法取消。您可以使用的有用语法when()和then()。
观察值:
Observable 是随时间推移的多个值的惰性集合。这确实是异步操作的好方法。它可以使用具有跨平台支持的rxjs来完成,可以与 Angular/React 等一起使用。
它的作用类似于流线型,可以是多管道。所以一旦定义好,就可以在很多地方订阅获取返回结果。
语法: import * as Rx from "@reactivex/rxjs";
初始化:
Rx.Observable.fromEvent(button, "click"),
Rx.Subject()
Run Code Online (Sandbox Code Playgroud)
等等。
认购: 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));
Run Code Online (Sandbox Code Playgroud)
由于它支持多管道,您可以在不同的位置订阅结果,
它有比承诺更多的可能性。
用法:
它有更多的可能性,比如map、filter、pipe、map、concatMap等。
简短的回答:
观察到的是更好的。它具有所有Promises功能以及额外的功能。
长答案:
承诺:
观察值:
虽然Günter Zöchbauer 的回答总体上很好,但我认为它并没有强调在处理 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();
});
}
Run Code Online (Sandbox Code Playgroud)
如果你的组件在 promise 被解决之前被销毁,你会attempt to use destroyed view在 promise 被解决时得到一个错误。
或者,如果您将 observable 与takeUntil模式一起使用,那么一旦您的组件被销毁,订阅就会被取消。
这是一个有点人为的例子,但是为被销毁的组件执行代码可能会导致错误。
我看到很多人使用 Observable 是“可取消的”这一论点,但让 Promise “可取消”是相当微不足道的
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 200Run Code Online (Sandbox Code Playgroud)
承诺:是 ES6 的一项功能,用于处理异步代码,该代码在创建时立即执行,当时只能发出单个值并且不可取消。随着现代应用程序和功能需求的复杂性,如果我们要同时执行许多承诺,或者在执行之前进行过滤或进行一些转换,则有必要实现复杂的代码:
\nmyPromise.then((resolvedValue) => {\n console.log(resolvedValue);\n}, (error) => {\n console.log(error);\n});\nRun Code Online (Sandbox Code Playgroud)\nObservable:是 Rxjs 库提供的一个对象,可帮助我们在 JavaScript 应用程序中进行反应式编程,它提供链接和订阅来处理复杂的应用程序,具有可取消的优点,同时提供许多值。此外,我们可以从应用其他运算符(如retry()、map()、filter()、switchMap()等)的链接中受益,这有助于处理复杂的用例和繁重的用户界面。
即时搜索示例:
\nsearch(terms: Observable<string>) {\n return terms.pipe(\n debounceTime(400),\n distinctUntilChanged(),\n switchMap((term) => this.searchEntries(term))\n );\n }\nRun Code Online (Sandbox Code Playgroud)\n并行调用多个 APIS 的示例:
\nlet character = this.http.get('https://jsonplaceholder.typicode.com/todos');\n let characterHomeworld = this.http.get(\n 'https://jsonplaceholder.typicode.com/posts'\n );\n\n forkJoin([character, characterHomeworld]).subscribe((results) => {\n console.log('result \xc2\xb0', results[0]);\n console.log('result 1', results[1]);\n });\nRun Code Online (Sandbox Code Playgroud)\n
另一个区别:全球与进口
Promise是一个标准的内置对象,你可以直接使用它。在此处检查浏览器支持。
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) });Run Code Online (Sandbox Code Playgroud)
JavaScript 的可观察、反应式扩展需要RxJS 安装并在使用前导入
import { Observable } from 'rxjs';
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
420052 次 |
| 最近记录: |