Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use .takeUntil() over .take(1) with Http service?

Tags:

angular

rxjs

ngrx

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());
  }
}
like image 442
JoshuaDavid Avatar asked Jan 15 '17 03:01

JoshuaDavid


1 Answers

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.

like image 149
cartant Avatar answered Nov 15 '22 22:11

cartant