1

I have an API endpoint that's returning an array of strings (json) and I'm trying to create a page that spits out the contents via an Angular Service. Here's what I have thus far (I'm on Angular 7):

export class FieldService {
  constructor(private httpClient: HttpClient) { }

  fieldTypesURL = 'http://localhost:3000/fields/types';

  public getTypes(): Observable<any[]> {
    return this.httpClient.get<any[]>(this.fieldTypesURL)
    .pipe(map((response: any) => response.json()),
      catchError((error: any) => Observable.throw(error.json().error || 'Server error')));
  }
}

The compilation error I'm getting is the following:

Type 'Observable<any[]>' is missing the following properties from type 'Promise<string[]>': then, catch, [Symbol.toStringTag], finally

Why is it mentioning a Promise here while I'm trying to use an Observable? Any ideas welcome!

8
  • 1
    I think you can skip pipe in this case, code seems fine Commented Feb 5, 2019 at 4:52
  • 1
    with httpClient it's NOT necesary response.json() Commented Feb 5, 2019 at 7:50
  • What version of TypeScript are you using? (As defined in your package.json file) Commented Feb 5, 2019 at 7:52
  • I'm using Typescript version: ~3.2.2 Commented Feb 5, 2019 at 19:16
  • 2
    you evidently are trying to assign getTypes() return value to something you have defined as Promise<any[]> Commented Feb 13, 2019 at 8:16

4 Answers 4

1

When you are using httpClient, it automatically parses the response as JSON. So, the .pipe(map((response: any) => response.json()) could be the error here.

Also, type 'any' changed to 'string'

Give this a shot:

public getTypes(): Observable<string[]> {
return this.httpClient.get<string[]>(this.fieldTypesURL)
  .catch((error: any) => Observable.throw(( error && JSON.parse(error).error) || 'Server error')));
}

The .json() function does almost* the same thing as can be seen here Angular Response.json() not documented

Sign up to request clarification or add additional context in comments.

3 Comments

I simplified the code by removing that line and end up with a much nicer version, but I'm still running into the exact same error. I've tried a ton of variants recommended from this post with no luck either: stackoverflow.com/questions/37208801/…
Sorry about that. See above.
public getTypes(): Observable<any[]> { return this.httpClient.get<any[]>(this.fieldTypesURL); } ... is my current code and it's throwing the same error.
0

@hamzakhan rightly said that we don't need to parse the response as json. But as your code is still not working try this I have just changed Observable to Observable in return type of function getTypes(). Hope it works good luck..!!!!!

export class FieldService {
  constructor(private httpClient: HttpClient) { }

  fieldTypesURL = 'http://localhost:3000/fields/types';

  public getTypes(): Observable<any> {
    return this.httpClient.get(this.fieldTypesURL)
    .pipe(map((response: any) => console.log(response),
      catchError((error: any) => Observable.throw(( error && JSON.parse(error).error) || 'Server error')));
  }
}

Comments

0

1) Calling httpClient with a generic argument makes the json conversion and type cast for you.

2) Observable#throw has been deprecated, use the throwError operator instead. Also, make sure you parse & handle your error correctly. Having a type for your error will definitely increase the type safety.

3) Make sure you call your service method correctly...

// field.service.ts
export class FieldService {

  constructor(private httpClient: HttpClient) { }

  fieldTypesURL = 'http://localhost:3000/fields/types';

  public getTypes(): Observable<string[]> {
    return this.httpClient.get<string[]>(this.fieldTypesURL).pipe(
      catchError((r: HttpErrorResponse) => throwError(r.error || 'Server error'))
    );
  }
}
// your.component.ts
export class YourComponent {

  constructor(private fieldService: FieldService){}

  // ... component logic ...

  public types: string[];
  public types$: Observable<string[]>;

  public callService() {

    // A correct call
    this.fieldService.getTypes().subscribe(types => this.types = types)

    // Also a correct call with a bit of observable stream processing
    this.types$ = this.fieldService.getTypes().pipe(
      catchError((err: any) => {
        // Component-side error processing can be put here
        return throwError(err);
      }),
      flatMap(types => types),
      filter(type => !!type),
      map(type => type.trim()),
      toArray()
    );

    // Incorrect calls (compiler errors)
    this.fieldService.getTypes().then(types => /* whatever */);
    this.fieldService.getTypes().catch(err => /* whatever */);
    let r: Promise<string[]> = this.fieldService.getTypes();
  }
}

Hope this helps a little :-)

Comments

0

Use the following code as catchError(this.handleError) will take care of your errors as well as failed Http requests.

export class FieldService {
  constructor(private httpClient: HttpClient) { }

  fieldTypesURL = 'http://localhost:3000/fields/types';

  public getTypes(): Observable<any[]> {
    return this.httpClient.get<any[]>(this.fieldTypesURL)
    .pipe(
      catchError(this.handleError)
    );
  }

  private handleError(error: HttpErrorResponse) {

    if (error.error instanceof ErrorEvent) {
      // A client-side or network error occurred. Handle it accordingly.
      console.log('An error occurred:', error.error.message);
    } else {
      // The backend returned an unsuccessful response code.
      // The response body may contain clues as to what went wrong,
      console.log(
        `Backend returned code ${error.statusText}, ` +
        `body was: `,error.message);
    }
    // return an observable with a user-facing error message
    return _throw('Something went wrong. Please try again later.');
  };
}

If you notice, I removed .map() from the code just because it was used to perform some action on the response data, which is not required.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.