Context: I am working on implementing @ngrx/effects within an @ngrx/store project and studying the example app.
Question: In the BookEffects class file, line #50, why is takeUntil(...)
used instead of take(1)
? Both would seem to accomplish the same thing in this case.
@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([])));
});
}
And here is the Google Books service file:
@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());
}
}
To understand why takeUntil
is used, it might help to make no assumptions about the implementation of searchBooks
.
The searchBooks
service method returns an observable of Book[]
. That observable does not necessarily have to complete; for instance, it could emit additional results if the database changes (this is what happens with Firebase's AngularFire2 observables). However, if take(1)
is used, subsequent results will be ignored. If takeUntil
is used, subsequent results will continue to effect actions until the next search is initiated.
However, I don't think the takeUntil
is essential, as the switchMap
will take care of things (the inner observable will be unsubscribed, etc.).
The author(s) of the example-app
appear to have implemented the search effect in such a way that it is not dependent upon the implementation of the service.
With the simple, Http
-based implementation of searchBooks
, I cannot see why either take(1)
or takeUntil
would be required - as the observable will complete and the switchMap
will ensure that SearchCompleteAction
actions for stale searches are not emitted.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With