试图在javascript中重播GPX路线,但在延迟航路点方面苦苦挣扎

时间:2017-06-26 22:00:05

标签: javascript node.js rxjs

我有很多GPX文件包含我想在node.js脚本中重播的路由。这是为了支持测试地理应用程序,因此我希望以与捕获路径时相同的时间差重放路点。例如,如果我有这样的文件:

<?xml version="1.0" encoding="UTF-8"?>
<gpx
  version="1.1"
  creator="Runkeeper - http://www.runkeeper.com"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://www.topografix.com/GPX/1/1"
  xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
  xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1">
<trk>
  <name><![CDATA[Running 7/9/13 5:12 pm]]></name>
  <time>2013-07-09T22:12:45Z</time>
<trkseg>
<trkpt lat="46.414311000" lon="-94.356703000"><ele>386.7</ele><time>2013-07-09T22:12:45Z</time></trkpt>
<trkpt lat="46.414328000" lon="-94.356708000"><ele>386.0</ele><time>2013-07-09T22:12:46Z</time></trkpt>
<trkpt lat="46.414404000" lon="-94.356637000"><ele>385.6</ele><time>2013-07-09T22:12:49Z</time></trkpt>
<trkpt lat="46.414486000" lon="-94.356562000"><ele>385.4</ele><time>2013-07-09T22:12:52Z</time></trkpt>
...

我希望我的脚本处理第一个点,等待1秒,然后处理第二个点,等待3秒再处理第三个点,然后再处理3秒钟再处理最后一点...依此类推。它可能根本不重要,但是我正在获取这些数据并更新一个firebase数据库,所以还有其他的#as;&#34; async&#34;我需要对每个数据点做的事情。

我可以将数据放入数组中没有问题,所以我尝试使用一个带有一些setTimeout调用的简单foreach循环,但我同时触发了一堆更新,其中每个都有一些延迟。然后我尝试使用像这样的observable:

    // waypoints is an array of the ... waypoints
    //
    Observable.from(waypoints)
        .zip(Observable.timer(0, 1000), x => x)
        .subscribe(async waypoint => {
            // await'ing firebase stuff
        });

这让我用很少的代码延迟每个数据点,但只是固定的数量,而不是使用每个航路点之间的间隔。我试图用处理数据点的变量替换1000,但是却无法使其工作。

有没有其他方法可以使用observables(或其他东西)来获得这种行为?

我看到js真的不能同步工作,但我花了很多时间在C#中所以我并不反对只使用它,但我希望学到新的东西:)

1 个答案:

答案 0 :(得分:1)

您可以使用startWithpairwise运算符发出前一个和当前的航点,然后可以将concatMap运算符与延迟了适当数量的可观察值一起使用:

const waypoints = Rx.Observable.from([{
  lat: 46.414311000,
  lon: -94.356703000,
  time: Date.parse("2013-07-09T22:12:45Z")
}, {
  lat: 46.414328000,
  lon: -94.356708000,
  time: Date.parse("2013-07-09T22:12:46Z")
}, {
  lat: 46.414404000,
  lon: -94.356637000,
  time: Date.parse("2013-07-09T22:12:49Z")
}, {
  lat: 46.414486000,
  lon: -94.356562000,
  time: Date.parse("2013-07-09T22:12:52Z")
}]);

const replay = waypoints
  .startWith(null)
  .pairwise()
  .concatMap(([previous, current]) => previous ?
    Rx.Observable.of(current).delay(current.time - previous.time) :
    Rx.Observable.of(current)
  )
  .subscribe(waypoint => console.log(waypoint));
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/rxjs@5/bundles/Rx.min.js"></script>