4

In Angular 7 I am getting and posting data from an API.

GET

  • To get data I am using an Observable (posts$) and pipe / map;
  • I am using async in the Component HTML and not using Subscribe;
  • This is the approach I have seen recently including in Angular docs.

POST

  • The Service Post method also returns data:
    Possible validation errors or the ID of the created Post.
    I need to get any of them when they are returned by the API.

However, when calling the service to POST the following does nothing:

this.postService.addPost(model).pipe();

Unless I use subscribe as follows:

this.postService.addPost(model).pipe().subscribe();

Question How would I post to the API without using subscribe? And does it make sense?

Component

export class PostComponent implements OnInit {

  posts$: Observable<GetPostsModel[]>;

  constructor(private postService: PostService) { }

  ngOnInit() {
    this.posts$ = this.getPosts();
  }

  addPost(model: AddPostModel) {

    this.postService.addPost(model).pipe().subscribe();

  }

  getPosts(): Observable<GetPostsModel[]> {

    return this.postService.getPosts().pipe(

      map((response: GetPostsResponse) => 

        return {
          // Map Response to GetPostsModel here 
        };

      }));

  }

}

Service

export class PostService {

  constructor(private httpClient: HttpClient) { }

  public addPost(model: AddPostModel): Observable<AddPostResponse>> {

    const headers = new HttpHeaders({ 'Content-Type': 'application/json' });

    return this.httpClient.post<AddPostResponse>>('posts', model, { headers: headers });

  }

  public getPosts(): Observable<GetPostsResponse>> {
    return this.httpClient.get<GetPostsResponse>>('posts');
  }

}
Miguel Moura
  • 36,732
  • 85
  • 259
  • 481
  • 2
    Possible duplicate of [Angular 2 http.post() is not sending the request](https://stackoverflow.com/questions/36208732/angular-2-http-post-is-not-sending-the-request) – Igor Feb 21 '19 at 18:17
  • 2
    You need to use subscribe on an observable. "An Observable instance begins publishing values only when someone subscribes to it" - https://angular.io/guide/observables#subscribing – Nathan Beck Feb 21 '19 at 18:17
  • One way would be to use RxJS connectable observables. – alt255 Feb 21 '19 at 18:51

2 Answers2

4

How would I post to the API without using subscribe?

You can't, you must always subscribe. If you do not care about the result you do not have to supply a callback. This is perfectly valid:

this.postService.addPost(model).subscribe();

side note: you do not need an empty pipe in this case

See also Angular 2 http.post() is not sending the request and HttpClient - Always subscribe! documentation.

Always subscribe!

An HttpClient method does not begin its HTTP request until you call subscribe() on the observable returned by that method. This is true for all HttpClient methods.

Igor
  • 60,821
  • 10
  • 100
  • 175
1

The Observable returned by any of the Http operations (get/post/put/etc) require a subscription.

But in some cases, Angular automatically handles that subscription for you.

For example:

  • Using an async pipe will automatically subscribe to the returned observable.

  • Using a route resolver will automatically subscribe to the returned observable.

In every other case, such as your Post example, you need to subscribe.

UPDATE

You only need to add the pipe if you need to pipe the response through a set of operators. Normally, you would at least want the catchError operator. I often add tap during development just for debugging purposes, but it is not necessary.

Here is an example of one of my Post operations:

  createProduct(product: Product): Observable<Product> {
    const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
    return this.http.post<Product>(this.productsUrl, product, { headers: headers })
      .pipe(
        tap(data => console.log('createProduct: ' + JSON.stringify(data))),
        catchError(this.handleError)
      );
  }

I don't often see the use of the pipe in the client code. For "separation of concerns", normally the data mapping/manipulation is done in the service ... unless there is something component-unique that you need to do.

But just this:

this.postService.addPost(model).pipe().subscribe();

Piping without piping the response through some operators doesn't do anything.

DeborahK
  • 57,520
  • 12
  • 104
  • 129
  • Thank you for the explanation ... Is there any advantage of using pipe in this.postService.addPost(model).pipe().subscribe()? I mean, I could simply use map() and catch error inside subscribe? Or should I use pipe() and in there use map and catchError() and just call subscribe() at the end? – Miguel Moura Feb 21 '19 at 19:58