2017-06-14 158 views
1

我創建了一項服務,它使用RxJS來包裝$http調用。Angular 1服務 - RxJS共享運營商不能正常工作

我有幾個組件訂閱相同的observable,我希望他們共享AJAX結果,而不是多個請求。

服務代碼:

export function SearchService($http) { 
    'ngInject'; 

    const autocompleteResults$ = new Subject() 
     .debounceTime(250) 
     .switchMap(query => Observable.fromPromise($http.post('/search', { query }))) 
     .share() 
     .map(result => result.data); 


    function autocomplete(query) { 
     autocompleteResults$.next(query); 
    } 

    return { 
     autocomplete, 
     autocompleteResults$ 
    }; 
} 

組件的代碼:

export const myComponent = { 
    bindings: { 
     query: '<' 
    }, 
    templateUrl: templateUrl, 
    controller: myController 
}; 

function myController($SearchService) { 
    'ngInject'; 
    const $ctrl = this; 

    $ctrl.$onInit = $onInit; 
    $ctrl.$onChanges = $onChanges; 

    function $onInit() { 
     SearchService.autocompleteResults$ 
      .subscribe(
       handleSuccess, 
       handleError 
      ); 
    } 

    function $onChanges(changes) { 
     if (changes.query && changes.query.currentValue) 
      SearchService.autocomplete(changes.query.currentValue); 
    } 
} 

我有,要查詢的變化做出反應的myComponent活性組分。

由於Angular服務是單身,每個組件應該得到訂閱它的時候,卻總是有相同的觀察到的實例2 AJAX調用,而不是1

我使用sharepublishpublishReplayshareReplay嘗試和refCount運營商沒有成功。

回答

1

你所描述的看起來更像是你正在尋找緩存而不是共享和Observable。

當您使用share()時,您只是將共享的訂閱與其源Observable共享,而不是其結果。

例如,如果一個HTTP請求需要100毫秒,那麼這將讓兩個請求使用share()即便:

const source = this.http.get(...).share(); 
source.subscribe(...); 

setTimeout(() => source.subscribe(...), 1000); 

share()運營商不幫助你在這裏,因爲在所有的第一個HTTP請求完成後觀察員取消訂閱,share()內的主題也取消訂閱。然後,在1秒後,您再次訂閱,並需要重新訂閱,這會再次發出HTTP請求。

但是,如果你做了以下那麼你會做只有一個HTTP請求:當第二觀察者簽約第一個是仍處於活動狀態,並且通過share()被播

const source = this.http.get(...).share(); 
source.subscribe(...); 
source.subscribe(...); 

。因此,您只需進行一次HTTP調用。

也許你正在尋找的東西像這樣的重放1秒接收值:

const source = this.http.get(...) 
    .publishReplay(1, 1000) 
    .refCount() 
    .take(1);