背景信息:我正在@ngrx/effects项目中实施@ngrx/store并研究example app。
问题:在BookEffects class file第50行,为什么使用takeUntil(...)
代替take(1)
?在这种情况下,两者似乎都会完成同样的事情。
@Injectable()
export class BookEffects {
constructor(private actions$: Actions, private googleBooks: GoogleBooksService) { }
@Effect()
search$: Observable<Action> = this.actions$
.ofType(book.ActionTypes.SEARCH)
.debounceTime(300)
.map((action: book.SearchAction) => action.payload)
.switchMap(query => {
if (query === '') {
return empty();
}
const nextSearch$ = this.actions$.ofType(book.ActionTypes.SEARCH).skip(1);
return this.googleBooks.searchBooks(query)
.takeUntil(nextSearch$)
.map(books => new book.SearchCompleteAction(books))
.catch(() => of(new book.SearchCompleteAction([])));
});
}
@Injectable()
export class GoogleBooksService {
private API_PATH: string = 'https://www.googleapis.com/books/v1/volumes';
constructor(private http: Http) {}
searchBooks(queryTitle: string): Observable<Book[]> {
return this.http.get(`${this.API_PATH}?q=${queryTitle}`)
.map(res => res.json().items || []);
}
retrieveBook(volumeId: string): Observable<Book> {
return this.http.get(`${this.API_PATH}/${volumeId}`)
.map(res => res.json());
}
}
答案 0 :(得分:4)
要了解使用takeUntil
的原因,可能有助于对searchBooks
的实施做出任何假设。
searchBooks
服务方法返回Book[]
的可观察量。这种可观察性并不一定要完成;例如,如果数据库发生变化,它可能会发出额外的结果(这就是Firebase的AngularFire2 observable所发生的情况)。但是,如果使用take(1)
,则后续结果将被忽略。如果使用takeUntil
,则后续结果将继续执行操作,直到启动下一次搜索。
然而,我并不认为takeUntil
是必不可少的,因为switchMap
会照顾事物(内部可观察者将被取消订阅等)。
example-app
的作者似乎已经以不依赖于服务实现的方式实现了搜索效果。
使用基于Http
的简单searchBooks
实现,我无法理解为什么需要take(1)
或takeUntil
- 因为observable将完成,{ {1}}将确保不会发出针对陈旧搜索的switchMap
操作。
答案 1 :(得分:-1)
take(n)从可观察序列的开头返回指定数量的连续元素
takeUntil(Observable | Promise)返回源可观察序列中的值,直到其他可观察序列或Promise产生值。您应该使用takeUntil
来管理RxJS订阅
1)当你杀了你的流时它会触发一个完成事件
2)更少的实际订阅点(因为对subscribe
的呼叫次数减少)
了解更多信息,请阅读本文https://medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87#.ge4d447b6