Search code examples
angularvisual-studio-codeobservable

Debugging Angular HttpClient observables: where can I set a breakpoint to see what's returned from the server?


I'm new to Angular and "reactive programming".

I have an Angular 8 component (test-api.component.*) that uses a service (contacts.service.ts) to talk to a REST back-end. It looks like this:

test-api.component.ts:

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { Contact } from '../models/contact';
import { ContactsService } from '../services/contacts.service';

@Component({
  selector: 'app-test-api',
  templateUrl: './test-api.component.html',
  styleUrls: ['./test-api.component.css']
})
export class TestAPIComponent implements OnInit {

  // "$" convention denotes this as an "Observable"
  contacts$: Observable<Contact[]>;

  constructor(private contactsService: ContactsService) { }

  ngOnInit() {
    this.loadContacts();
  }

  loadContacts() {
    this.contacts$ = this.contactsService.getContacts();
  }
}

test-api-component.html:

<h1>Contacts</h1>
<p *ngIf="!(contacts$ | async)"><em>Loading...</em></p>
<table class="table table-sm table-hover" *ngIf="(contacts$ | async)?.length > 0">
  <thead>
    <tr>
      <th>ContactId</th>
      <th>Name</th>
      <th>EMail</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let contact of (contacts$ | async)">
      <td>{{ contact.ContactId }}</td>
      <td>{{ contact.Name }}</td>
      <td>{{ contact.EMail }}</td>
    </tr>
  </tbody>
</table>

I'm developing with Visual Studio code.

How/where can I set a breakpoint in my code so I can see my contacts[] array in the debugger after the async operation has completed? I just want to be able to look at individual "contact" elements in the debugger.

Update

I know how to set breakpoints and use JS debuggers (both VSCode/Chrome extensions and Chrome Developer Tools), but I didn't know how best to modify the code so that I could examine the data that was otherwise going straight into the HTML template.

Andrei Gătej gave the most detailed answer to my implicit questions (what exactly is happening "under the covers" when I declare an "Observable" or pipe "async"?)

Both Mustafa Kunwa and Himanshu Singh gave me effectively the SAME answer - the one that I went with.

Solution

Anyway, my final code looks like this:

test-api.component.html

 <tr *ngFor="let contact of (contactsList)">
      <td>{{ contact.contactId }}</td>
      <td>{{ contact.name }}</td>
      <td>{{ contact.eMail }}</td>
 ...

test-api.component.ts

export class TestAPIComponent implements OnInit, OnDestroy {

  contactsList: Contact[];
  private contactsSubscription$: Subscription;
  ...
  ngOnInit() {
    this.contactsSubscription$ =
      this.contactsService.getContacts().subscribe(
        data => {
          this.contactsList = data;
          console.log('loadContacts', data);
        },
        err => {
          console.error('loadContacts', err);
        });
  ...
  ngOnDestroy() {
    this.contactsSubscription$.unsubscribe();
  }

Solution

  • try this

     this.contactsService.getContacts().subscribe(
         res=>{
          console.log(res);
         },
         err=>{
           console.log(err);
         });