我通过一个简单的ajax调用加载一个初始数据数组并将该数据放入和Observable,我将其称为历史。与此同时,我连接到websocket并定期接收数据,我们将其称为更新,我想将此数据附加到历史。
具体来说,让我们说ajax调用会发回数组[0,1,2]
,套接字会随着时间的推移3
,4
,5
然后发出想要像这样累积这些值:
[0,1,2] // historical
[0,1,2,3] // historical + updates1
[0,1,2,3,4] // historical + updates1 + updates2
[0,1,2,3,4,5] // etc
(请注意,此处必须处理并发边缘情况:历史会产生 最终目标是以单个Observable 流结束,这是所描述的Observables 历史和更新的组合。 只是累积websocket数据很容易。我创建更新,这是websocket发出的Observable序列。每次观察到一个值,我都可以使用 这会产生类似 我的下一个问题是如何将其与历史相结合。由于历史的数据可能在已经观察到一个或多个更新后到达,因此在等待历史>时需要累积这些更新。我设法使用 观察流会产生一个值[0,1,2,3]
以及前两个更新< / strong>是3
和4
,在这种情况下,我最终想要的仍然是[0,1,2,3,4]
- 不 [0,1,2,3,3,4]
。)< / p>
到目前为止我已尝试过:
scan()
:updates.scan((acc, update) => acc.concat([update]), [])
[3]
[3,4]
[3,4,5]
withLatestFrom()
:const stream = historical
.withLatestFrom(
updates.scan((acc, update) => acc.concat([update]), []),
(history, buffer) => history.concat(buffer) /* could eliminate duplicates here */
)
[0,1,2,3,4,5]
,它是历史与更新的组合。 >历史
但是,我无法弄清楚从哪里去。如何继续将更新附加到流,以便随着时间的推移流产生如下内容:
[0,1,2,3,4,5]
[0,1,2,3,4,5,6]
[0,1,2,3,4,5,6,7]
我没有看到使用scan
的方法,就像我为更新所做的那样,因为在这种情况下我需要scan
&#39 ; s的初始(种子)值是Observable,而不是Array。
有没有办法做到这一点 - 通过添加到目前为止的内容或更好的替代方式来完成整个事情?
答案 0 :(得分:3)
如果我理解正确的话,我会使用skipUntil()
运算符继续收集更新,而不会进一步发布。然后对于withLatestFrom()
运算符,我会选择updates
Observable作为其来源。这等待感谢skipUntil()
,直到历史数据可用,然后在updates
的每次发射时发出。
let updates = Observable
.timer(0, 1000)
.scan((acc, update) => {
acc.push(update);
return acc;
}, []);
let historical = Observable.defer(() => {
console.log('Sending AJAX request ...');
return Observable.of(['h1', 'h2', 'h3']);
})
.delay(3000)
.share();
const stream = updates.skipUntil(historical)
.withLatestFrom(historical, (buffer, history) => {
return history.concat(buffer);
})
.map(val => val) // remove duplicates;
stream.subscribe(val => console.log(val));
控制台中的输出如下:
Sending AJAX request ...
["h1", "h2", "h3", 0, 1, 2, 3]
["h1", "h2", "h3", 0, 1, 2, 3, 4]
["h1", "h2", "h3", 0, 1, 2, 3, 4, 5]
查看现场演示:https://jsbin.com/kumolez/11/edit?js,console
我不知道您使用的是什么,但我会尽量避免使用concat()
,因为buffer
增长时可能会变慢。
此外,如果您在更新时发布了一个项目(而不是累积它们),您可以使用distinct()
运算符来过滤掉重复项。