RxJS:将历史数据与更新流相结合

时间:2017-02-14 20:29:54

标签: javascript rxjs

情景:

我通过一个简单的ajax调用加载一个初始数据数组并将该数据放入和Observable,我将其称为历史。与此同时,我连接到websocket并定期接收数据,我们将其称为更新,我想将此数据附加到历史

具体来说,让我们说ajax调用会发回数组[0,1,2],套接字会随着时间的推移345然后发出想要像这样累积这些值:

[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

(请注意,此处必须处理并发边缘情况:历史会产生[0,1,2,3]以及前两个更新< / strong>是34,在这种情况下,我最终想要的仍然是[0,1,2,3,4] - [0,1,2,3,3,4]。)< / p>

最终目标是以单个Observable 结束,这是所描述的Observables 历史更新的组合。

到目前为止我已尝试过:

只是累积websocket数据很容易。我创建更新,这是websocket发出的Observable序列。每次观察到一个值,我都可以使用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。

有没有办法做到这一点 - 通过添加到目前为止的内容或更好的替代方式来完成整个事情?

1 个答案:

答案 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()运算符来过滤掉重复项。

是的,我假设您正在使用RxJS 5.