简体   繁体   中英

Trying to return RxJS observable stream from exported function

I have a React-Native app that uses the library react-native-sensors to access the mobile device's accelerometer data (x, y, and z-axis). The react-native-sensors library utilizes RxJS observables, something I am unfamiliar with.

In an earlier version of the app, the App component would set its own state to the device's live accelerometer data. This occurred inside the component's constructor function, where the accelerometer observable used the subscribe operator to call 'setState'. This approach had the desired effect ie the App component's state continued to update at regular intervals as the device moved.

At this stage the App component looked like this:

import React, { Component } from "react"; 
import { setUpdateIntervalForType, SensorTypes, accelerometer } from "react-native-sensors";

export default class App extends Component {   
  constructor(props) {
    super(props);

    setUpdateIntervalForType(SensorTypes.accelerometer, 150);

    accelerometer.subscribe(({ x, y, z }) => {
      this.setState({ x, y, z }),
        error => {
          console.log("The sensor is not available");
        };
    });

    this.state = { x: 0, y: 0, z: 0 };   
  }

  render() {
  ...
  ...
  ...
  }
}

In order to improve encapsulation and perform better tests I decided to extract the accelerometer observable into a separate file and export it back into the App component. My intention was to export the observable as a function that would return a stream of values ie those emitted from the accelerometer. This is where I got stuck. My first attempt to export the observable data looked like this:

Accelerometer.js

import {
  setUpdateIntervalForType,
  SensorTypes,
  accelerometer
} from "react-native-sensors";

export default function AccelerometerData() {
   var data;

   setUpdateIntervalForType(SensorTypes.accelerometer, 150);

   accelerometer.subscribe(({ x, y, z }) => {
      data = { x, y, z }
   });

  return data;
 }

I appreciate this approach does not respect the asynchronous nature of RxJS observables. I'm also aware that there are other operators such as 'map' that may help here, but I'm not entirely sure how to implement it in this context.

You can just return it as an observable and chain it up with a setState wrapped in an Obervable

export default function AccelerometerData() {
   var data;

   setUpdateIntervalForType(SensorTypes.accelerometer, 150);

   return accelerometer
 }

Usage

setState(obj)=>
new Observable(obs=>this.setState(obj,()=>obs.next(this.state))
AccelerometerData().pipe(tap(obj=>setState(obj)).subscribe()

Thanks Fan Cheung. I eventually took this route:

 export async function accelerometerData() {
      setUpdateIntervalForType(SensorTypes.accelerometer, 150);

      return accelerometer;
    }

Usage:

async getAccelerometerData() {
    const accelerometer = await accelerometerData();

    accelerometer.subscribe(({ x, y, z }) => {
      this.setState({ x, y, z }),
        error => {
          console.log("The sensor is not available");
        };
    });
 }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM