title: Reactive search with RxJS Observable Vs Subject
body: <p>The following are two approaches to the same problem, is to do a reactive search for some characters that user enter in a text box. The first solution is from <a href="https://github.com/ngrx/example-app/blob/master/src/app/effects/book.ts" rel="nofollow noreferrer">ngrx example</a> and the second one is from an <a href="https://egghead.io/courses/build-an-angular-2-instant-search-component" rel="nofollow noreferrer">egghead</a> instant search course.</p>
  
  <ul>
  <li>The first solution uses <code>Observable</code> while the second uses <code>Subject</code>.</li>
  <li>The <code>Observable</code> solution uses <code>takeUntil</code> to call the server only once. The <code>Subject</code> solution uses <code>distinctUntilChanged</code>.</li>
  </ul>
  
  <p>Can someone explain the advantages and disadvantages with these two approaches?</p>
  
  <p>Search using Observable:</p>
  
  <pre><code>@Injectable()
  export class BookEffects {
  
    @Effect()
    search$: Observable&lt;Action&gt; = this.actions$
      .ofType(book.ActionTypes.SEARCH)
      .debounceTime(300)
      .map(toPayload)
      .switchMap(query =&gt; {
        if (query === '') {
          return empty();
        }
  
        const nextSearch$ = this.actions$.ofType(book.ActionTypes.SEARCH).skip(1);
  
        return this.googleBooks.searchBooks(query)
          .takeUntil(nextSearch$)
          .map(books =&gt; new book.SearchCompleteAction(books))
          .catch(() =&gt; of(new book.SearchCompleteAction([])));
      });
  
      constructor(private actions$: Actions, private googleBooks: GoogleBooksService) { }
  }
  
  @Component({
    selector: 'bc-find-book-page',
    changeDetection: ChangeDetectionStrategy.OnPush,
    template: `
      &lt;bc-book-search [query]="searchQuery$ | async" [searching]="loading$ | async" (search)="search($event)"&gt;&lt;/bc-book-search&gt;
      &lt;bc-book-preview-list [books]="books$ | async"&gt;&lt;/bc-book-preview-list&gt;
    `
  })
  export class FindBookPageComponent {
    searchQuery$: Observable&lt;string&gt;;
    books$: Observable&lt;Book[]&gt;;
    loading$: Observable&lt;boolean&gt;;
  
    constructor(private store: Store&lt;fromRoot.State&gt;) {
      this.searchQuery$ = store.select(fromRoot.getSearchQuery).take(1);
      this.books$ = store.select(fromRoot.getSearchResults);
      this.loading$ = store.select(fromRoot.getSearchLoading);
    }
  
    search(query: string) {
      this.store.dispatch(new book.SearchAction(query));
    }
  }
  </code></pre>
  
  <p>Search using Subject:</p>
  
  <pre><code>import { Component } from '@angular/core';
  import { WikipediaSearchService } from './wikipedia-search.service';
  import { Subject } from 'rxjs/Subject';
  
  //application wide shared Rx operators
  import 'rxjs/add/operator/map';
  import 'rxjs/add/operator/debounceTime';
  import 'rxjs/add/operator/distinctUntilChanged';
  import 'rxjs/add/operator/switchMap';
  
  @Component({
    moduleId: module.id,
    selector: 'app-root',
    templateUrl: 'app.component.html',
    styleUrls: ['app.component.css']
  })
  export class AppComponent {
    items:Array&lt;string&gt;;
    term$ = new Subject&lt;string&gt;();
    constructor(private service:WikipediaSearchService) {
  
      this.term$
          .debounceTime(400)
          .distinctUntilChanged()
          .switchMap(term =&gt; this.service.search(term))
          .subscribe(results =&gt; this.items = results);
    }
  }
  
  &lt;div&gt;
    &lt;h2&gt;Wikipedia Search&lt;/h2&gt;
    &lt;input (input)="term$.next($event.target.value)"&gt;
    &lt;ul&gt;
      &lt;li *ngFor="let item of items"&gt;{{item}}&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
  </code></pre>