我有一些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数据库,因此我需要对每个数据点进行其他“异步”处理。
我可以毫无问题地将数据放入数组,所以我尝试使用带有一些setTimeout调用的简单foreach循环,但是我同时触发了许多更新,每个更新都被延迟了一段时间。然后我尝试使用像这样的可观察对象:
// 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
,但仍无法使它正常工作。是否有另一种方法使用可观察对象(或其他方法)来获得此行为?
我看到js确实不是要同步工作,但是我在C#中花了很多时间,所以我不反对只使用它,而是希望学习新的知识:)
最佳答案
您可以使用startWith
和pairwise
运算符发出先前和当前的航路点,然后可以将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>