Search code examples
angularros

Passing variables from an observable subscription Angular 6


I'm not sure if I'm doing this completely wrong, but I'm trying to get this data assigned to a variable so I can use it in the parent class. This is a service in angular 6. Here's the whole services' code.

import {Injectable} from '@angular/core';
import { Observable } from 'rxjs';
import '../assets/roslib.js';

@Injectable({
  providedIn: 'root'
})

export class RoslibService {
  // Creates object with the ROS library
  // @ts-ignore <= Makes ts happy, wont error
    ros = new ROSLIB.Ros({
      // Set listen URL for ROS communication
    url : 'ws://localhost:9090'
  });
  // Data variable to hold ROS data
  data: any = "Not Touched";
  // Initialize function sets everything up, called on a ngOnInit in app.component
  initialize() {
    let data = "UnTouch";
    // Listens for error from ROS and logs it
    this.ros.on('error', function(error) {
      console.log(error);
    });

    // Find out exactly when we made a connection.
    this.ros.on('connection', function() {
      console.log('Connection made!');
    });
    // Logs when connection is closed
    this.ros.on('close', function() {
      console.log('Connection closed.');
    });

    // Get Data from ROS
    // @ts-ignore
      const driveControlListener = new ROSLIB.Topic({
      ros : this.ros, // Points to ROS variable
      name : '/drive_control/parameter_updates', // Topic Name
      messageType : 'dynamic_reconfigure/Config' // Message Type
    });

    // Subscribe to ROS data
     driveControlListener.subscribe((message) => {
      console.log('Recieved Message on ' + driveControlListener.name + ' : ' + message.bools);
      data = message;
      return message;
    });
     this.data = data;
  }

  getDriveControlData(): Observable<any> {
    console.log(this.data);
    return this.data;
  }
  getThrustersState(): Observable<any> {
    console.log("Getting Thruster State");
    console.log(this.data);
    return this.data;
  }
}

The driveControlListener is returning a stream of data, so I'm trying to assign that data to a variable and use it in the rest of my app.


Solution

  • you can achieve this with the use of Subjects. Simply make the variable data as type Subject. Example:

    data: BehaviorSubject<any> = new BehaviorSubject('Untouched');
    

    Then

      // Subscribe to ROS data 
    
    driveControlListener.subscribe((message) => { 
    console.log('Recieved Message on ' + driveControlListener.name + ' : ' + message.bools); 
    this.data.next(message);
    });
    
    
    // define a getter for data
    getData() {
    return this.data.asObservable();
    }
    

    So for every place you want to use the data variable in your app, simply subscribe to it. Example:

    this.rosLibService.getData().subscribe(data => {
    console.log(data);
    });
    

    You can learn more about Subjects in rxjs official docs, hope this helps 🙂