Angular 6 / Rxjs - 基础知识:Observables 成功、错误、最后
Angular 6 / Rxjs - how to basics: observables success, error, finally
我正在构建一个基于最新 Angular 6 的架构并且来自 AngularJS 有一些我不能安心的事情:HTTP 请求的基本处理。
所以,为了这个问题,假设我想要一个 observable。因为这似乎是Angular.
的未来
我从一些非常优雅的东西开始,在 AngularJS 中:
service.getAll()
.then(onSuccess) // I process the data
.catch(onError) // I do whatever needed to notify anyone about the issue
.finally(onFinally); // I stop the loading spinner and other stuff
现在Angular6/RxJS 6,我不明白为什么一切都那么复杂,看起来也不对。
我可以找到两种方法来做与上面相同的事情:
满管
this.service.getAll()
.pipe(
map((data) => this.onSuccess(data)),
catchError(error => of(this.handleError(error))),
finalize(() => this.stopLoading())
)
.subscribe();
由于我们必须使用管道进行最终确定,所以我还不如对所有内容都使用管道,我认为最好以相同的顺序排列所有内容。但是现在我们不得不抛出一些东西,叫做"of"(不太好理解)我不喜欢那样。
半管
所以我尝试了另一个想法,只使用我需要的管道(完成)并保留订阅回调。
this.service.getAll()
.pipe(
finalize(() => this.stopLoading())
)
.subscribe(
(data) => this.onSuccess(data),
(error) => this.handleError(error)
);
但是,嗯。是不是有点落后了?我们仍然有没有实际名称的回调,我们在读取处理和错误之前完成。奇怪。
所以有些事情我绝对不明白。而且我在网上找不到与这个基本问题相关的任何内容。您要么有人想要 "success and finally",要么有人想要 "success and error",但没有人想要其中 3 个。
也许我太老了,我不明白新的最佳实践(如果是这样,请教育我!)。
我的需求很简单:
1. 我想处理从服务中获取的数据
2.我想获取错误以便显示给用户
3. 我想在调用之前停止我刚刚启动的加载微调器,或者在第一个完全成功或错误后再次调用(我真的想要一个 finally)
您如何使用 observable 处理基本的 HTTP 调用?
(我不想要任何 .toPromise
,拜托,我想了解如何处理新内容)
Observable的subscribe
方法接受3个可选函数作为参数
- 第一个处理由引发的事件附带的数据
Observable
- 第二个处理任何错误
- 第三个在 Observable 完成时做某事
所以,如果我没理解错的话,你想要的可以用这样的代码实现
this.service.getAll()
.subscribe(
data => this.onSuccess(data),
error => this.handleError(error),
() => this.onComplete()
);
考虑到在出现竞争条件(通过使用 switchMap
运算符)时重试(请参阅 retry
运算符)时,使用 Observables 进行 http 调用可以带来好处。我认为这些是 Angular 团队为 http 客户端选择这种方法的主要原因。
一般来说,我认为值得开始了解 Observables 的工作原理和一些最重要的运算符(除了上面的那些,我首先想到的是 mergeMap
、filter
、reduce
- 但还有很多其他的)很重要,因为它们可以显着简化异步非阻塞环境中的许多任务,例如浏览器(或 Node)。
我认为正确的方法是使用 Observable 函数:next,err,complete。
这是一个如何触发完整功能的示例。
假设我们有 BehaviorSubject 对象:
let arr = new BehaviorSubject<any>([1,2]);
现在假设我们想要订阅它,如果我们得到值 "finish" 我们想要完成。
let arrSubscription = arr.asObservable().subscribe(
data => {
console.log(data)
if(data === 'finish') {
arr.complete()
}
},
err => {
console.log(err)
},
() => {
console.log("Complete function triggered.")
}
);
arr.next([3,4])
arr.next('finish')
arr.next([5,6])
控制台日志为:
[1,2]
[3,4]
finish
Complete function triggered.
由于我们触发了 complete 函数,我们的 BehaviorSubject 的最后一个 .next 不会被触发,因为 err 和 complete 函数是订阅的终止符。
这只是您如何触发完整功能的示例,从这里您可以做任何您想做的事。
我认为有一个关键的误解:
You either have someone who wants "success and finally", or "success and error" but none wants the 3 of them.
这不完全正确。每个 Observable 可以发送零个或多个 next
通知和一个 error
或 complete
通知,但不能同时发送。例如,当成功进行 HTTP 调用时,您将收到一个 next
和一个 complete
通知。在错误的 HTTP 请求上,您将只有一个 error
通知,仅此而已。参见 http://reactivex.io/documentation/contract.html
这意味着你永远不会有一个同时发出 error
和 complete
的 Observable。
然后是 finalize
运算符。在处理链时调用此运算符(也包括普通取消订阅)。换句话说,它在 error
和 complete
通知之后被称为 。
所以你的第二个例子是正确的。我知道在订阅之前包含 finalize
看起来很奇怪,但实际上来自源 Observable 的每个发射首先从上到下到达订阅者,如果它的 error
或 complete
通知它触发自下而上的处置处理程序(以相反的顺序),此时 finalize
被调用。参见 https://github.com/ReactiveX/rxjs/blob/master/src/internal/Subscriber.ts#L150-L152
在您的示例中,使用 finalize
与自己将处置处理程序添加到 Subscription
对象中相同。
const subscription = this.service.getAll()
.subscribe(
(data) => this.onSuccess(data),
(error) => this.handleError(error)
);
subscription.add(() => this.stopLoading());
我正在构建一个基于最新 Angular 6 的架构并且来自 AngularJS 有一些我不能安心的事情:HTTP 请求的基本处理。
所以,为了这个问题,假设我想要一个 observable。因为这似乎是Angular.
的未来我从一些非常优雅的东西开始,在 AngularJS 中:
service.getAll()
.then(onSuccess) // I process the data
.catch(onError) // I do whatever needed to notify anyone about the issue
.finally(onFinally); // I stop the loading spinner and other stuff
现在Angular6/RxJS 6,我不明白为什么一切都那么复杂,看起来也不对。
我可以找到两种方法来做与上面相同的事情:
满管
this.service.getAll() .pipe( map((data) => this.onSuccess(data)), catchError(error => of(this.handleError(error))), finalize(() => this.stopLoading()) ) .subscribe();
由于我们必须使用管道进行最终确定,所以我还不如对所有内容都使用管道,我认为最好以相同的顺序排列所有内容。但是现在我们不得不抛出一些东西,叫做"of"(不太好理解)我不喜欢那样。
半管 所以我尝试了另一个想法,只使用我需要的管道(完成)并保留订阅回调。
this.service.getAll() .pipe( finalize(() => this.stopLoading()) ) .subscribe( (data) => this.onSuccess(data), (error) => this.handleError(error) );
但是,嗯。是不是有点落后了?我们仍然有没有实际名称的回调,我们在读取处理和错误之前完成。奇怪。
所以有些事情我绝对不明白。而且我在网上找不到与这个基本问题相关的任何内容。您要么有人想要 "success and finally",要么有人想要 "success and error",但没有人想要其中 3 个。 也许我太老了,我不明白新的最佳实践(如果是这样,请教育我!)。
我的需求很简单:
1. 我想处理从服务中获取的数据
2.我想获取错误以便显示给用户
3. 我想在调用之前停止我刚刚启动的加载微调器,或者在第一个完全成功或错误后再次调用(我真的想要一个 finally)
您如何使用 observable 处理基本的 HTTP 调用?
(我不想要任何 .toPromise
,拜托,我想了解如何处理新内容)
Observable的subscribe
方法接受3个可选函数作为参数
- 第一个处理由引发的事件附带的数据 Observable
- 第二个处理任何错误
- 第三个在 Observable 完成时做某事
所以,如果我没理解错的话,你想要的可以用这样的代码实现
this.service.getAll()
.subscribe(
data => this.onSuccess(data),
error => this.handleError(error),
() => this.onComplete()
);
考虑到在出现竞争条件(通过使用 switchMap
运算符)时重试(请参阅 retry
运算符)时,使用 Observables 进行 http 调用可以带来好处。我认为这些是 Angular 团队为 http 客户端选择这种方法的主要原因。
一般来说,我认为值得开始了解 Observables 的工作原理和一些最重要的运算符(除了上面的那些,我首先想到的是 mergeMap
、filter
、reduce
- 但还有很多其他的)很重要,因为它们可以显着简化异步非阻塞环境中的许多任务,例如浏览器(或 Node)。
我认为正确的方法是使用 Observable 函数:next,err,complete。
这是一个如何触发完整功能的示例。
假设我们有 BehaviorSubject 对象:
let arr = new BehaviorSubject<any>([1,2]);
现在假设我们想要订阅它,如果我们得到值 "finish" 我们想要完成。
let arrSubscription = arr.asObservable().subscribe(
data => {
console.log(data)
if(data === 'finish') {
arr.complete()
}
},
err => {
console.log(err)
},
() => {
console.log("Complete function triggered.")
}
);
arr.next([3,4])
arr.next('finish')
arr.next([5,6])
控制台日志为:
[1,2]
[3,4]
finish
Complete function triggered.
由于我们触发了 complete 函数,我们的 BehaviorSubject 的最后一个 .next 不会被触发,因为 err 和 complete 函数是订阅的终止符。
这只是您如何触发完整功能的示例,从这里您可以做任何您想做的事。
我认为有一个关键的误解:
You either have someone who wants "success and finally", or "success and error" but none wants the 3 of them.
这不完全正确。每个 Observable 可以发送零个或多个 next
通知和一个 error
或 complete
通知,但不能同时发送。例如,当成功进行 HTTP 调用时,您将收到一个 next
和一个 complete
通知。在错误的 HTTP 请求上,您将只有一个 error
通知,仅此而已。参见 http://reactivex.io/documentation/contract.html
这意味着你永远不会有一个同时发出 error
和 complete
的 Observable。
然后是 finalize
运算符。在处理链时调用此运算符(也包括普通取消订阅)。换句话说,它在 error
和 complete
通知之后被称为 。
所以你的第二个例子是正确的。我知道在订阅之前包含 finalize
看起来很奇怪,但实际上来自源 Observable 的每个发射首先从上到下到达订阅者,如果它的 error
或 complete
通知它触发自下而上的处置处理程序(以相反的顺序),此时 finalize
被调用。参见 https://github.com/ReactiveX/rxjs/blob/master/src/internal/Subscriber.ts#L150-L152
在您的示例中,使用 finalize
与自己将处置处理程序添加到 Subscription
对象中相同。
const subscription = this.service.getAll()
.subscribe(
(data) => this.onSuccess(data),
(error) => this.handleError(error)
);
subscription.add(() => this.stopLoading());