我创建了一个使用RxJS
来回复$http
次呼叫的服务。
我有几个订阅同一个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);
}
}
我有 2 myComponent
的有效组件来响应查询更改。
由于Angular
服务是单例,每个组件在订阅它时应该获得相同的可观察实例,但总有2个AJAX调用而不是1个。
我尝试使用share
,publish
,publishReplay
,shareReplay
和refCount
运营商但没有成功。
答案 0 :(得分: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请求:
const source = this.http.get(...).share();
source.subscribe(...);
source.subscribe(...);
当第二个观察者订阅时,第一个观察者仍处于活动状态,并通过share()
进行多播。因此,您只需拨打一个HTTP电话。
也许你正在寻找这样的东西,重播1s的收到价值:
const source = this.http.get(...)
.publishReplay(1, 1000)
.refCount()
.take(1);