【问题标题】:Loading indicator on Http requestsHttp 请求的加载指示器
【发布时间】:2017-01-04 13:33:55
【问题描述】:

我的问题的根源是在 http 请求上显示加载指示器,我想在服务级别执行此操作,而无需为每个组件编写代码。我所做的是实现一个 http 包装器,它基本上是这样做的:

getMyHttpObservable(...) {
    setLoadingIndicator(true);
    const myHttpObservable = 
        createRequestObservable().finally(()=> {
            console.log('http done');
            setLoadingIndicator(false);
        });
    return myHttpObservable;
}

我有一个可观察的序列,我使用Observable.concat 链接如下:

const t1 = Observable.timer(5000).finally(()=>console.log('t1 done'));
const t2 = getMyHttpObservable(...);
const agg = Observable.concat(t1,t2);

我正在使用Observable.takeUntil 使用基于事件的取消技术,如下所示:

const ev = new EventEmitter<any>();
const cancellableAgg = agg.takeUntil(ev.asObservable());

现在的问题是,当我在第一个计时器期间取消聚合 observable 时,我没有得到第二个 observable 的 finally 调用 - http 请求。示例:

const cancel = Observable.timer(500).finally(()=>ev.emit());
cancellableAgg.subscribe();
cancel.subscribe();

当上面运行时,我得到这个输出:

t1 done

我还需要获取http done,以便清除加载指示器。我怎样才能做到这一点?

谢谢!

编辑

我没有意识到 concat 操作员只订阅了 observables ,当他们的前辈完成时。我需要的是仅在实际订阅了 http observable 时才激活加载指示器。

我修改了我的包装函数如下:

getMyHttpObservable(...) {
    const myHttpObservable = createRequestObservable(...);
    const subscriptionAware = new Observable(subscriber => {
        setLoadingIndicator(true);
        myHttpObservable.subscribe(
            nextEv => subscriber.next(nextEv),
            errEv => subscriber.error(errEv),
            () => subscriber.complete())
        .add(()=>setLoadingIndicator(false));
    };
    return subscriptionAware;
}

所以基本上,我创建了一个Observable,它透明地包装了另一个Observable,但在实际订阅时还会执行一些额外的操作——激活加载指示器。

但是,现在我失去了在运行中取消 XHR 请求的能力,因为 Observable 的构造函数不允许我传递取消处理程序,因此内部订阅永远不会被取消。

关于如何实现这一点的任何想法?

【问题讨论】:

  • 我会建议一种不同的方法,即定义一个 decorator 以应用于您想要放置微调器的方法。将微调器置于 http 级别不够灵活,并且会将网络逻辑与 UI 恕我直言混淆。

标签: angular typescript rxjs typescript1.8


【解决方案1】:

设法使用内置的 defer 运算符找到解决方案,该运算符等待订阅并返回一个新的 observable:

getMyHttpObservable(...) {
    const myHttpObservable = createRequestObservable(...);
    return Observable.defer(() => {
        setLoadingIndicator(true);
        return myHttpObservable.finally(() => setLoadingIndicator(false));
    });
}

优雅而简短。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-09
    • 1970-01-01
    • 2019-04-12
    • 2017-10-14
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    • 2018-01-07
    相关资源
    最近更新 更多