gh9
gh9

Reputation: 10693

Angular subscription on observable returns undefined

My Service

import { Injectable } from "@angular/core";
import { Observable, of } from "rxjs";
import { SearchResult } from "../Components/container-search/Models/SearchResult";
import { environment } from "../../environments/environment";
import { HttpClient, HttpHeaders } from "@angular/common/http";

@Injectable({
  providedIn: "root",
})
export class ContainerService {
  constructor(public http: HttpClient) {}

  private SearchResults: SearchResult[] = [];
  public headers = {
    headers: new HttpHeaders({
      "Content-Type": "application/json",
    }),
  };

  public Search(): Observable<SearchResult[]> {
    if (this.SearchResults.length === 0) {
       this.http
        .get<SearchResult[]>(
          environment.endpointURL + "/FooBar/Search",
          this.headers
        )
        .subscribe((x) => {
          this.SearchResults = x;
          return of(this.SearchResults);
        });
    } else {
      return of(this.SearchResults);
    }
  }
}

When I call Search() in my component it returns

TypeError: Cannot read property 'subscribe' of undefined

My calling code is

  ngOnInit(): void {
    this.dataSource.paginator = this.paginator;
     this.searchService.Search().subscribe((x) => {
      this.dataSource = new MatTableDataSource<SearchResult>(x);
    });
  }

Can someone explain why this code this.searchService.Search() would always return with the above error?

Upvotes: 0

Views: 93

Answers (1)

peinearydevelopment
peinearydevelopment

Reputation: 11474

The .subscribe call is returning an Observable, but that isn't what's being returned by the Search method. The subscription is an asynchronous process. The subscribe kicks off that process and only reacts when the http call returns, but the Search method keeps executing and returns undefined.

The below code will return the Observable from the http call directly and fix your issue.

import { tap } from 'rxjs/operators';

public Search(): Observable<SearchResult[]> {
    if (this.SearchResults.length === 0) {
       return this.http
        .get<SearchResult[]>(
          environment.endpointURL + "/FooBar/Search",
          this.headers
        ).pipe(tap(x => this.SearchResults = x));
    } else {
      return of(this.SearchResults);
    }
  }

Upvotes: 1

Related Questions