在用 Angular 做项目的时候, 遇到了一个有点麻烦的问题. 具体问题如下:
轮循请求某个接口, 如何保证接口返回的数据与请求的顺序相同?
实际的业务场景是这样的: 前端需要轮循请求后端接口获取文件处理进度, 并在前端用进度条展示. 如下方所示:
首先想到的肯定是使用 setTimeout 或者 setInterval 进行定时请求. 然而结果有点诡异, 进度条的变化不是递增, 而是有快有慢, 比如 30%,20%,50%,40% 这样. 仔细一想也知道问题出在哪, 异步请求的结果并不是按顺序返回的.
我在之前的工作中还没有遇到过这类需求, 所以我并不是很清楚如果用传统方式应该如何解决. 然而很庆幸的是 RxJS 正好擅长处理这样的问题. 我立即翻了一下文档, interval 操作符可以处理定时任务, 而且更强大的是返回结果也是有顺序的.
interval(period: 0 = 0, scheduler: SchedulerLike = async): Observable<number>
首先看一下 interval 的说明:
创建一个可观察对象, 在规定的调度程序中, 以规定的时间间隔发出连续的数值.
interval 返回一个可观察对象, 它可以周期性的发出递增数值, 但是第一次发出值是在第一个周期结束之后执行的.
以下是官方例子:
- import {
- interval
- } from 'rxjs';
- import {
- take
- } from 'rxjs/operators';
- const numbers = interval(1000);
- const takeFourNumbers = numbers.pipe(take(4));
- takeFourNumbers.subscribe(x => console.log('Next:', x));
- // Logs:
- // Next: 0
- // Next: 1
- // Next: 2
- // Next: 3
不过只看官方例子还是有点懵, 如果是 http 请求的话应该怎么写参数呢? 或者说应该把 http 请求写在哪里?
这个地方的坑有点深, 通过翻阅外文资料终于找到答案. 直接上代码.
- // 间隔 1s 请求
- this.timer$ = interval(1000)
- .pipe(
- // 取消过时的请求值
- switchMap(() => {
- return this.http.get(API);
- }),
- )
- .subscribe(
- (res: any) => {
- // 百分数处理逻辑
- },
- () => {
- this.timer$.unsubscribe();
- },
- () => {
- this.timer$.unsubscribe();
- },
- );
总的来说就是通过管道处理请求. 最终的效果很完美.
总结
RxJS 确实是一个非常强大的工具库, 尤其处理异步交互真的是省时省力, 但是国内技术文章偏少, 遇到疑难问题还需要查阅国外文章. 欢迎大家评论交流.
来源: https://www.cnblogs.com/nzbin/p/10956065.html