2016-11-29 67 views
2

我有一个订阅,它具有异步步骤api调用。虽然API调用正在进行中,但我想显示加载动画。它可以很容易地done时流与访问用户界面创建:在RxJs中跟踪异步操作

Rx.Observable 
    .combineLatest(page$, sorting$) 
    .switchMap(function(args) { 
     var page = args[0]; 
     var sorting = args[1]; 

     $('.overlay').show(); 

     return loadData(page, sorting); 
    }) 
    .subscribe(function(data) { 
     renderData(data); 
     $('.overlay').hide(); 
    }); 

但是当我移动流管理代码到service(如代码重用)来跟踪异步操作的能力失去了,我不能显示加载动画。

任何想法如何完成?从服务中返回两个流?

在此先感谢。

回答

2

为什么不创建一个包含多个 '事件' 流 - startedfinished,这样的事情:

function loadDataWithStartEvent($page, sorting$) { 
    return Rx.Observable 
    .combineLatest(page$, sorting$) 
    .flatMap(args => { 
     var page = args[0]; 
     var sorting = args[1]; 

     return Rx.Observable.just({ event : 'started' }) 
     .concat(
      // given that loadData returns an Observable<data> which only emits data one time 
      loadData(pageSortingTuple.page, pageSortingTuple.sorting)) 
      .map(data => ({ event: 'finished', data: data})) 
     ); 
    });  
} 

现在您订阅如下:

loadDataWithStartEvent(page$, sorting$) 
    .doOnNext(evt => { 
    if(evt.type == 'started') { 
     $('overlay').show(); 
    } else { 
     $('overlay').hide(); 
    } 
    }) 
    .filter(evt => evt.type === 'finished') 
    .map(evt => evt.data); 
    .subscribe(data => renderData(data)); 
+0

看起来不错,谢谢! –

1

您可以通过一个额外的通知对象为setupLoading

setupLoading: function(page$, sorting$, notify$) { 
    return Rx.Observable 
    .combineLatest(page$, sorting$) 
    .switchMap(function(args) { 
     notify$.next(true); // here we go... 
     var page = args[0]; 
     var sorting = args[1]; 

     return loadData(page, sorting); 
    }); 
} 

,然后创建,除了page$sorting$loadStarted$观测。

loadStarted$.subscribe(() => $('.overlay').hide(); 

,并为您的装载机创作将是:

service.setupLoading(page$, sorting$, loadStarted$) 
    .subscribe(function(data) { 
    renderData(data); 
    }); 
}); 

顺便说一句,因为你使用rxjs得这么好,为什么不使用它的显示/隐藏 - 在angular2方式 - 放弃的jQuery:

<div class="overlay" [style.display]="(showOverlay ? 'block' : 'none')>your overlay content here</div> 
+0

附加流,我明白了。我希望能有一些不可思议的方法来避免它,但可能没有。 –

+0

为了简单起见,我使用了jQuuery,在真正的应用程序中我确实使用了角度2。 –

0

最后,我结束了使用运营商定制:

class RequestState { 
    loading: boolean; 
} 


Observable.prototype.captureState = function captureState<T>(this: Observable<T>, state: RequestState): Observable<T> { 
    state.loading = true; 

    let onLoadingEnd =() => { 
    state.loading = false; 
    }; 

    obs = obs.do(onLoadingEnd, onLoadingEnd, onLoadingEnd); 

    return obs; 
}; 


class Component { 
    requestState = new RequestState(); 

    ngOnInit() { 
    this.api.endpoint(query) 
     .captureState(this.requestState) 
     .subscribe(...); 
    } 
}