Robouste
Robouste

Reputation: 3680

Angular : Observable not working

I don't exactly know what is going wrong but I'm trying to apply the search system from the angular doc with no success.

Here are the function used in the component :

// my-comp.component.ts
public testing: Observable<any>;
private searchTerms = new Subject<string>();

search(term: string): void {
    this.searchTerms.next(term.toUpperCase());
}

This function is hit each time I type something in the searchbox so no problem here.

Here is the ngOnInit method :

// my-comp.component.ts
ngOnInit(): void {

    this.testing = this.searchTerms
        .debounceTime(300)        // wait 300ms after each keystroke before considering the term
        .distinctUntilChanged()   // ignore if next search term is same as previous
        .switchMap(term => term   // switch to new observable each time the term changes
            // return the http search observable
            ? this.refundCaseService.search(term)
            // or the observable of empty heroes if there was no search term
            : this.test(term)
        )
        .catch(error => {
            // TODO: add real error handling
            console.log(error);
            return Observable.of<any>();
        });

}

test(term: string) {
    console.log(term);
    return Observable.of<any>();
}

This code is never reached, it doesn't enter the service neither the test function (I used breakpoints and console.log to make sure).

I don't understand how this is working.

Using: Angular 4.0.0 Angular-cli 1.0.6

Upvotes: 2

Views: 1813

Answers (3)

Nico Van Belle
Nico Van Belle

Reputation: 5146

Check this excellent article from Christoph Burgdorf on THOUGHTRAM - Cold vs Hot Observables.

Basically, what you are dealing with here is known as a Cold Observable.

Cold observables start running upon subscription, i.e., the observable sequence only starts pushing values to the observers when Subscribe is called. (…) This is different from hot observables such as mouse move events or stock tickers which are already producing values even before a subscription is active.

So, unless you subscribe to this.testing or use the async pipe in your template, no requests will be fired.

Upvotes: 1

eko
eko

Reputation: 40647

The other answers are correct that this is indeed a Cold Observable. However, the reason that this is actually working is the async pipe of Angular.

The async pipe that's been used in the example:

<div id="search-component">
  <h4>Hero Search</h4>
  <input #searchBox id="search-box" (keyup)="search(searchBox.value)" />
  <div>
    <div *ngFor="let hero of heroes | async"
         (click)="gotoDetail(hero)" class="search-result" >
      {{hero.name}}
    </div>
  </div>
</div>

because of this pipe this example is working.

The async pipe subscribes to an Observable or Promise and returns the latest value it has emitted. When a new value is emitted, the async pipe marks the component to be checked for changes. When the component gets destroyed, the async pipe unsubscribes automatically to avoid potential memory leaks.

Source: https://angular.io/api/common/AsyncPipe


tl;dr: you can't debug this code because it's being handled in the template/html.

Upvotes: 3

koninos
koninos

Reputation: 5327

You have to subscribe to the Observable otherwise it doesn't "listen" for changes.

   this.testing.subscribe(
        x => console.log('onNext: %s', x),
        e => console.log('onError: %s', e),
        () => console.log('onCompleted')
    );

Upvotes: 1

Related Questions