简体   繁体   English

如何从不是初始值的无限 RxJs stream 中获取单个最新值?

[英]How can I get the single latest value from an infinite RxJs stream that is not the initial value?

The concept这个概念

This is a mocked angular2 project.这是一个模拟的 angular2 项目。

When consuming the observable stream from the redux store I tried to filter first and then take/takeLast/last the latest value.当从 redux 商店消费可观察的 stream 时,我尝试先过滤,然后取/取最后/最后一个最新值。 After that I want to resolve the promise when the stream completes but it does not when using takeLast operator.之后,我想在 stream 完成时解析 promise,但在使用 takeLast 运算符时却没有。

So the question is: What operator setup can I use to get the latest value from the stream ?所以问题是:我可以使用什么运算符设置来从 stream 获取最新值

The setup设置

I simplified my Angular 2 setup to this gist of RxJs usage.我将我的 Angular 2 设置简化为 RxJs 用法的要点。

  • source observable is managed by redux library and is not completed source observable 由 redux 库管理,未完成
  • service is providing some logic to retrieve the latest value from the stream服务正在提供一些逻辑来从 stream 中检索最新值
  • component is consuming value promise style组件正在消耗值 promise 样式

Here is a working example: https://fiddle.jshell.net/markus_falk/an41z6g9/这是一个工作示例: https://fiddle.jshell.net/markus_falk/an41z6g9/

The redux store mock: redux 商店模拟:

var latestTime$ = new Rx.Subject();
setInterval(function(){
     latestTime$.onNext(Date.now()); 
}, 2000);

The service injectable mock:服务可注入模拟:

var timeStore = null;
var getLatestTime = function() {

  return new Promise((resolve, reject) => {

     latestTime$

     /* 
        filter out 'null' for when the button is clicked
        before the store updates the first time
      */
     .filter(function(x) {
        console.log('filter: ', x);
        return x === typeof('number');
     })

     // try to end to stream by taking the last from the stream ?!?!?!?
     .takeLast(1)

     // handle promise
     .subscribe(

       function (x) {
         console.log('Next: ' + x);
         // store latest stream value
         timeStore = x;
       },
       function (err) {
         console.log('Error: ' + err);
         reject(err)
       },
       function () {
         console.log('Completed');
         // pass on latest value of endless when stream completes 
         resolve(timeStore);
       }

    );

  });

};

And a consuming mock component:和一个消费模拟组件:

document.querySelector("#foo").addEventListener("click", function(event) {

  var time = getLatestTime();

  time.then((latestTime) => {
    console.log('latestTime: ', latestTime);
  });

  time.catch((err) => {
    console.log('oh oh: ', err);
  });

}, false);

This should simulate your situation. 这应该模拟你的情况。

See live demo: https://jsfiddle.net/usualcarrot/zh07hfrc/1/ 观看现场演示: https//jsfiddle.net/usualcarrot/zh07hfrc/1/

var subject = new Rx.Subject();

subject.skip(1).last().subscribe(function(val) {
  console.log('next:', val);
}, function(val) {
  console.log('error:', val);
}, function() {
  console.log('completed');
});

subject.onNext(1);
subject.onNext(2);
subject.onNext(3);
subject.onNext(4);
subject.onNext(5);
subject.onCompleted();

This prints to console: 这打印到控制台:

next: 5
completed

Instead of console.log('completed'); 而不是console.log('completed'); you'd put the resolve(...) . resolve(...) Maybe this is not even necessary and you can use just return the Subject and subscribe to it as well (?) depending on your use case. 也许这甚至不是必需的,您可以使用只返回Subject并订阅它(?),具体取决于您的用例。 In that case use asObservable() to hide the fact you're using a Subject . 在这种情况下,使用asObservable()隐藏您正在使用Subject的事实 See similar use-case with asObservable() . 请参阅asObservable()类似用例

I use combineLatest for such scenarios.我在这种情况下使用combineLatest Here is a simple POC:这是一个简单的 POC:


import { ReplaySubject, combineLatest, of } from 'rxjs';

const source = new ReplaySubject();

source.next('1');
source.next('2');
source.next('3');

combineLatest([source, of(true)]).subscribe(([data]) => {
  console.log('data:', data) // data: 3
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM