如果请求很慢则显示加载

如果请求很慢则显示加载

本文介绍了RxJS:如果请求很慢则显示加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

本来想用RxJS来优雅的解决这个问题,但是尝试了各种方法后,还是不知道怎么做...

I thought of using RxJS to solve elegantly this problem, but after trying various approaches, I couldn't find out how to do it...

我的需求很普遍:我做了一个 Rest 调用,即.我有一个承诺.如果响应很快,我只想使用结果.如果它来得很慢,我想显示一个微调器,直到请求完成.这是为了避免微调器的闪光,然后是数据.

My need is quite common: I do a Rest call, ie. I have a Promise.If the response comes quickly, I just want to use the result.If it is slow to come, I want to display a spinner, until the request completes.This is to avoid a flash of a the spinner, then the data.

也许可以通过制作两个 observable 来完成:一个带有承诺,另一个带有超时并将微调器显示为副作用.我尝试了 switch() 没有成功,也许是因为另一个 observable 没有产生值.

Maybe it can be done by making two observables: one with the promise, the other with a timeout and showing the spinner as side effect.I tried switch() without much success, perhaps because the other observable doesn't produce a value.

有人实现过类似的东西吗?

Has somebody implemented something like that?

推荐答案

基于@PhiLho 的 answer,我写了一个管道操作符,它正是这样做的:

Based on @PhiLho's answer, I wrote a pipeable operator, which does exactly that:

export function executeDelayed<T>(
    fn : () => void,
    delay : number,
    thisArg? : any
) : OperatorFunction<T, T> {
    return function executeDelayedOperation(source : Observable<T>) : Observable<T> {
        let timerSub = timer(delay).subscribe(() => fn());
        return source.pipe(
            tap(
                () => {
                    timerSub.unsubscribe();
                    timerSub = timer(delay).subscribe(() => fn());
                },
                undefined,
                () => {
                    timerSub.unsubscribe();
                }
            )
        );
    }
}

基本上它返回一个函数,该函数获取Observable source.
然后它使用给定的 delay 启动一个 timer.
如果此计时器发出 next 事件,则调用该函数.
但是,如果源发出 next,则 timer 将被取消,并启动一个新的计时器.
在源码的complete中,最后取消了timer.然后可以像这样使用此运算符:

Basically it returns a function, which gets the Observable source.
Then it starts a timer, using the given delay.
If this timer emits a next-event, the function is called.
However, if the source emits a next, the timer is cancelled and a new one is startet.
In the complete of the source, the timer is finally cancelled.This operator can then be used like this:

this.loadResults().pipe(
    executeDelayed(
        () => this.startLoading(),
        500
    )
).subscribe(results => this.showResult())

我自己没有编写很多操作符,所以这个操作符实现可能不是最好的,但它有效.
欢迎任何有关如何优化它的建议:)

I did not wirte many operators myself, so this operator-implementation might not be the best, but it works.
Any suggestions on how to optimize it are welcome :)

正如@DauleDK 提到的,在这种情况下,错误不会停止计时器,并且 fn 将在 delay 之后被调用.如果这不是你想要的,你需要在 tap 中添加一个 onError-回调,它调用 timerSub.unsubscribe():>

As @DauleDK mentioned, a error won't stop the timer in this case and the fn will be called after delay. If thats not what you want, you need to add an onError-callback in the tap, which calls timerSub.unsubscribe():

export function executeDelayed<T>(
    fn : () => void,
    delay : number,
    thisArg? : any
) : OperatorFunction<T, T> {
    return function executeDelayedOperation(source : Observable<T>) : Observable<T> {
        let timerSub = timer(delay).subscribe(() => fn());
        return source.pipe(
            tap(
                () => {
                    timerSub.unsubscribe();
                    timerSub = timer(delay).subscribe(() => fn());
                },
                () => timerSub.unsubscribe(),   // unsubscribe on error
                () => timerSub.unsubscribe()
            )
        );
    }
}

这篇关于RxJS:如果请求很慢则显示加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 16:18