2016-11-29 426 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(...); 
    } 
}