如何使用 RxJS 更優雅地進行定時請求

在用 Angular 作項目的時候,遇到了一個有點麻煩的問題。具體問題以下:前端

輪循請求某個接口,如何保證接口返回的數據與請求的順序相同?後端

實際的業務場景是這樣的:前端須要輪循請求後端接口獲取文件處理進度,並在前端用進度條展現。以下方所示:api

首先想到的確定是使用 setTimeout 或者 setInterval 進行定時請求。然而結果有點詭異,進度條的變化不是遞增,而是有快有慢,好比 30%,20%,50%,40%這樣。仔細一想也知道問題出在哪,異步請求的結果並非按順序返回的。app

我在以前的工做中尚未遇到過這類需求,因此我並非很清楚若是用傳統方式應該如何解決。然而很慶幸的是 RxJS 正好擅長處理這樣的問題。我當即翻了一下文檔interval 操做符能夠處理定時任務,並且更強大的是返回結果也是有順序的。異步

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

首先看一下 interval 的說明:async

建立一個可觀察對象,在規定的調度程序中,以規定的時間間隔發出連續的數值。工具

interval 返回一個可觀察對象,它能夠週期性的發出遞增數值,可是第一次發出值是在第一個週期結束以後執行的。this

如下是官方例子:code

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 確實是一個很是強大的工具庫,尤爲處理異步交互真的是省時省力,可是國內技術文章偏少,遇到疑難問題還須要查閱國外文章。歡迎你們評論交流。

相關文章
相關標籤/搜索