Search code examples
angularrxjsobservableangular2-observables

Cannot read property 'next' of undefined when using async pipe


I have a service like this, Which mocks an API call,

import { Injectable } from '@angular/core';
import { Observable, Subscriber} from 'rxjs';

import { DeviceStatus } from '../models/device-status-model';

@Injectable()
export class GetStatusService {
  public deviceStatusObserver: Subscriber<DeviceStatus>;
  public deviceStatus: Observable<DeviceStatus>;

  constructor() { 
    this.deviceStatus = new Observable(observer => {
      this.deviceStatusObserver = observer;
    });
  }

  getRandom(max): number {
    return Math.floor(Math.random() * Math.floor(max));
  }

  callApi() {
    setInterval(() => {
      //Mocking data
      let status = new DeviceStatus();
      status.tempC = this.getRandom(50) + 'C';
      status.tempF = this.getRandom(50) + 'F';
      status.humidity = this.getRandom(100) + '%';
      status.pin1 = true;
      status.pin2 = true;
      status.pin3 = true;
      status.pin4 = true;
      this.deviceStatusObserver.next(status);
    }, 500);
  }
}

And a component like this

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';


import { GetStatusService } from '../services/get-status.service';
import { DeviceStatus } from '../models/device-status-model'

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

  dStatus$: Observable<DeviceStatus>;

  humidityValue: string; tempValue: string;

  constructor(private getStatusService: GetStatusService) { 
    this.dStatus$ = getStatusService.deviceStatus;
  }

  ngOnInit() {
     this.getStatusService.deviceStatus.subscribe((data) => {
       this.tempValue = data.tempC;
       this.humidityValue = data.humidity;
     });
    this.getStatusService.callApi();
  }
}

I wanted to use this Observable with async pipe, so i removed

this.getStatusService.deviceStatus.subscribe((data) => {
           this.tempValue = data.tempC;
           this.humidityValue = data.humidity;
         });

Then I started to get ERROR TypeError: Cannot read property 'next' of undefined on console. Do I need to subscribe to an Observable even if i use async pipe. All the tutorials i looked up didn't use the subscriber method.

Link to the project in StackBlitz


Solution

  • Finally figured it out,

    changed added a null check in callApi()

      callApi() {
        setInterval(() => {
          let status = new DeviceStatus();
          status.tempC = this.getRandom(50) + 'C';
          status.tempF = this.getRandom(50) + 'F';
          status.humidity = this.getRandom(100) + '%';
          status.pin1 = true;
          status.pin2 = true;
          status.pin3 = true;
          status.pin4 = true;
          if(!this.deviceStatusObserver)
            return;
          this.deviceStatusObserver.next(status);
        }, 500);
      }