如何使用 RxJS 更优雅地进行定时请求

在用 Angular 做项目的时候,遇到了一个有点麻烦的问题。具体问题如下:

轮循请求某个接口,如何保证接口返回的数据与请求的顺序相同?

实际的业务场景是这样的:前端需要轮循请求后端接口获取文件处理进度,并在前端用进度条展示。如下方所示:

999445-20190531170304319-269435954.png

首先想到的肯定是使用 setTimeout 或者 setInterval 进行定时请求。然而结果有点诡异,进度条的变化不是递增,而是有快有慢,比如 30%,20%,50%,40%这样。仔细一想也知道问题出在哪,异步请求的结果并不是按顺序返回的。

我在之前的工作中还没有遇到过这类需求,所以我并不是很清楚如果用传统方式应该如何解决。然而很庆幸的是 RxJS 正好擅长处理这样的问题。我立即翻了一下文档interval 操作符可以处理定时任务,而且更强大的是返回结果也是有顺序的。

interval(period: 0 = 0, scheduler: SchedulerLike = async): Observable<number>

首先看一下 interval 的说明:

创建一个可观察对象,在规定的调度程序中,以规定的时间间隔发出连续的数值。

999445-20190531210226238-1652995715.png

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值