RXJS:拆分一个observable,过滤结果然后重新组合

时间:2017-04-16 09:35:32

标签: angular typescript rxjs observable

我有一个websocket,它以2Hz的速率返回GPS NMEA句子流。每个响应通常包含六个句子,包括两个GSV卫星可见性句子和一个GGA定位句子。每个GSV语句包含1-4个卫星的仰角,方位角和信噪比信息,这些是我最初感兴趣的句子。我想创建一个包含Satellite[]数组的可观察流目前可见的GNSS卫星的仰角和方位角细节。

以下打字稿代码片段每个GSV句子产生一个数组,但我想要的是每个响应的数组,可能包括几个GSV语句。我已经研究过使用concat,combine,merge和它们的变体但是没有成功。

最终我还想将GGA定位信息提取到另一个流中。

道歉,如果对此有一个简单的答案,我对RXJS来说相对较新,所以我找到了自己的方式。



// The information available for each satellite.

export interface Satellite {
    id: string;
    elevation: number;
    azimuth: number;
    noise: number;
}


// The code to process the web socket data.

this.satellites$ = <Subject<Satellite[]>> this.wss
    .connect('ws://localhost:8887')
    .mergeMap((response) => { return response.data.split(/\r?\n/); }) // Split the multi line response into individual lines.
    .filter((line) => line !== '')  // Filter out blank lines.
    .mergeMap((sentence) => { return this.nmeaPacket(sentence); }) // Parse the line into an NMEA sentence.
    .filter((packet) => { return packet.sentenceId === 'GSV'; })  // Filter out everything except GSV sentences.
    .map((gsvPacket: nmea.GSVPacket): Satellite[] => {
        // Extract the satellite info from this sentence.
        let satellites: Satellite[] = [];
        for (let satellite of gsvPacket.satellites) {
            if (satellite.prnNumber > 1) {
                satellites.push({
                    id: this.satelliteId(satellite.prnNumber),
                    azimuth: satellite.azimuthTrue,
                    elevation: satellite.elevationDegrees,
                    noise: satellite.SNRdB})
            }
        }
        return satellites;
    });  // Re-combine the array here or back where the initial line split is done??


// Use nmea-simple to parse a line from the response into an NMEA sentence.
 
private nmeaPacket(sentence: any): Observable<nmea.Packet> {
    return Observable.of(nmea.parseNmeaSentence(sentence));
}
&#13;
&#13;
&#13;

下面是一张大理石图,其中包含示例输入数据,显示了我希望如何处理这些数据。希望这可以更清楚地了解我想要实现的目标。

marble diagram showing processing

3 个答案:

答案 0 :(得分:0)

我认为您的问题会受益于输入和所需输出的示例,因为我不确定数组实际意味着什么重组。

此外,我不确定您的代码是否会产生评论中列出的行为。例如response.data.split(/\r?\n/)返回一个数组,但只有当.filter((line) => line !== '')是一个字符串并且该字符串为空时,true才会返回line

最后,如果你能澄清为什么satellites$是一个主题而不是一个ObservablenmeaPacket会返回一个与nmea.Packet相反的可观察对象,那将会有所帮助。

话虽如此,让我建议一些调整,看看是否有帮助:

this.satellites$ = this.wss
  .connect('ws://localhost:8887')
  .map((response) => response.data.split(/\r?\n/).filter((line) => line !== '') // <- can you provide an example of the input here
  .map((sentence) => this.nmeaPacket(sentence))
  .filter((packet) => packet.sentenceId === 'GSV')
  .map((packet) => {
    let satellites: Satellite[] = [];
    packet.satellites.forEach((satellite) => {
    
      if (satellite.prnNumber > 1) {
        satellites.push({
          id: this.satelliteId(satellite.prnNumber),
          azimuth: satellite.azimuthTrue,
          elevation: satellite.elevationDegrees,
          noise: satellite.SNRdB})
        }
      }
      
      return satellites;
      
    })
  }) // <- can you provide an example of the desired output here

private nmeaPacket(sentence: any): nmea.Packet {
  return nmea.parseNmeaSentence(sentence);
}

答案 1 :(得分:0)

要重新组合最后的行,您可以用map替换最后的reduce

Rx.Observable.of(1,2,3).reduce((acc, value) => [...acc, value], []).subscribe(console.log)

(...但我不确定Observables是否是正确的工具,你确定你不想只将每个响应映射到其他形状吗?在这种情况下一个简单的具有同步过滤器/映射操作的.map就足够了。)

答案 2 :(得分:0)

我怀疑这是最有效或最优雅的解决方案,但它确实实现了我的目标。有几个地方我不得不在卫星信息阵列上进行迭代,我在这些地方尝试过flatMap / mergeMap但是没有取得多大成功。

&#13;
&#13;
password
&#13;
&#13;
&#13;