首页 > 解决方案 > 合并 3 个订阅数据以加入新对象 rxjs Angular 9 中的数据

问题描述

我需要一些帮助来将来自 3 个不同传感器的数据合并到一个对象中,我使用一些 cordova-plugins 来获取 acc gyr 和 mag 数据,但我无法解决的问题是同时订阅所有 3 个 observables 并且将数据一起放入同一个对象中,我尝试递归调用 observables 但它不起作用,这是我的函数:

startGyroscope(){
  this.gyroscopeSerie = [];
  this.subscriptionGyro = this.gyr.watch({frequency : 75}).subscribe(
     (magnetometer: any) => {
       let data = {
         x: 0,
         z: 0,
         y: 0,
         timestamp: 0
       };
       data.x = magnetometer.x;
       data.y = magnetometer.y;
       data.z = magnetometer.z;
       data.timestamp = + new Date(),
       this.gyroscopeSerie.push(data);
     }
   );
 }

startMagnetometer(){
  this.magnometerSerie = [];
 this.subscriptionMag = this.mag.watchReadings().subscribe(
    (magnetometer: any) => {
      let data = {
        x: 0,
        z: 0,
        y: 0,
        timestamp: 0,
        magnitude: 0
      };
      data.x = magnetometer.x;
      data.y = magnetometer.y;
      data.z = magnetometer.z;
      data.timestamp = + new Date(),
      data. magnitude = magnetometer.magnitude
      this.magnometerSerie.push(data);
    }
  );
}



startAccelerometer(){
  this.accelerometerSerie = [];
  const frequency =  75;
  this.watchID = setInterval(() =>{
    this.watchAcceleration().then((accelerometer: any) =>{
      let data = {
        x: 0,
        z: 0,
        y: 0,
        timestamp: 0,
        roll: 0,
        pitch: 0,
        yaw: 0
      };
      data.x = accelerometer.x;
      data.y = accelerometer.y;
      data.z = accelerometer.z;
      data.roll = accelerometer.roll;
      data.pitch = accelerometer.pitch;
      data.yaw = accelerometer.yaw;
      data.timestamp = accelerometer.timestamp;
      this.accelerometerSerie.push(data);
    });
  },frequency);
}
// this plugin doesnt have an wrapper so i had to create a promise callback
watchAcceleration(){
  return new Promise((resolveCallback, rejectCallback) =>{
   new Promise((resolve, reject) =>{
    navigator.accelerometer.watchAcceleration(resolve,reject,{frequency : 75});
   }).then((acceleration) => {
      resolveCallback(acceleration);
   }).catch((error) =>{
     rejectCallback(error);
   });
  });
}

此对象中所有值的预期输出:

{ magx: 0 , magy: 0, magz: 0, accx: 0, accy: 0, accz: 0, roll: 0, pitch: 0, yaw: 0, girx: 0, giry: 0, girz: 0, timestamp: 0 };

提前致谢

标签: javascriptangularcordova

解决方案


如果我对您的理解正确,则这些可观察到的每一个都以大致相同的间隔发射,并且应该大约在同一时间。在所有三个可观察对象都发出新值并被组合之后,您只想拥有新的组合对象。为此,我会像这样混合结合 latest 和 distinctUntilChanged。(请原谅错别字,因为这是在我的手机上完成的)

gyrData: Observable <any>
magData: Observable <any>
accelData = new Subject<any>();
combined: Observable<any
combinedSub;

initCombinedData() {
   this.startGyroscope();
   this. startMagnetometer();
   this.startAccelerometer();
   this.combined = combineLatest([
      this.gyrData,
      this.magData,
      this.accelData
   ])
   .pipe(
      distinctUntilChanged((a, b) =>
        // emit only when all time stamps have update to avoid any lag in updates and ensure they stay in sync
         a[0].timestamp === b[0].timestamp ||
         a[1].timestamp === b[1].timestamp ||
         a[2].timestamp === b[2].timestamp ||
       ),
       map(([gyr, mag, acc]) => {
           const latestTime = Math.max(
              gyr.timestamp,
              mag.timestamp,
              acc.timestamp)
           
           return { magx: mag.x, magy: mag.y, magz: mag.z, accx: acc.x, accy: acc.y, accz: acc.z, roll: acc.roll, pitch: acc.pitch, yaw: acc.yaw, girx: gyr.x, giry: gyr.y, girz: gyr.z, timestamp: new Date(latestTime) };
       })
    )
    this.combinedSub = this.combined.subscribe();
}

startGyroscope(){
  this.gyrData = this.gyr.watch({frequency : 75})
  .pipe(
     map((magnetometer: any) => {
       const data = {
         x: magnetometer.x,
         z: magnetometer.z,
         y: magnetometer.y,
        timestamp: + new Date()
       };
       return data;
    })
 }

startMagnetometer(){
 this.magData = this.mag.watchReadings()
    .pipe(
       map((m: any) => {
         const data = {
           x: m.x,
           z: m.z,
           y: m.y,
          timestamp: + new Date(),
          magnitude: m. magnitude
         };
         return data;
       }
      );
    }

 startAccelerometer(){
   const frequency =  75;
   this.watchID = setInterval(() =>{
   this.watchAcceleration()
      .then((a: any) =>{
        const data = {
           x: a.x,
           z: a.z,
           y: a.y,
           timestamp: a.timestamp,
           roll: a.roll,
           pitch: a.pitch
           yaw: a.yaw,
         };
        this.accelData.next(data);
     });
   },frequency);
 }

 watchAcceleration(){
    return new Promise((resolveCallback, rejectCallback) =>{
    new Promise((resolve, reject) =>{
       navigator.accelerometer
          .watchAcceleration(resolve,reject, {frequency : 75});
      }).then((acceleration) => {
         resolveCallback(acceleration);
      }).catch((error) =>{
         rejectCallback(error);
    });
 });
}

推荐阅读