在Http请求上加载指示符

时间:2016-08-28 11:12:55

标签: angular typescript rxjs typescript1.8

我的问题的根源是在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的最终调用 - http请求。例如:

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

当上面的内容运行时,我得到了这个输出:

t1 done

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

谢谢!

修改

我没有意识到concat运算符仅在其前任已完成时才订阅可观察对象。我需要的是仅在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的{​​{1}},但是当它实际订阅时还会执行一些额外的操作 - 激活加载指示符。

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

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

1 个答案:

答案 0 :(得分:2)

使用内置defer运算符来管理查找解决方案,该运算符等待订阅并返回一个新的可观察对象:

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

优雅而简短。