简体   繁体   中英

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?

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);
    }
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM