如果另一个可观察对象在RxJS中有数据,如何忽略所有可观察对象? [英] How to ignore all from an observable if the other observable has data in RxJS?

查看:77
本文介绍了如果另一个可观察对象在RxJS中有数据,如何忽略所有可观察对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个观察对象,一个是从浏览器 localstorage 接收数据,另一个是从数据库通过 WebAPI 接收的数据.

I have two observables, one receives data from the browser localstorage and the other is from the database through WebAPI.

  1. 我要订阅它们,因此,如果 localstorage 中的可观察对象具有数据,请不要启动该对象以从数据库中获取数据.
  2. 如果 localstorage 中的可观测对象没有任何内容 数据,请调用 ajax 调用以从 WebAPI 获取数据.
  1. I want to subscribe to them so if the observable from the localstorage has data, don't initiate the one to get the data from the database.
  2. If the observable from the localstorage does not have any data, invoke the ajax call to get the data from the WebAPI.

在下面的示例中,我应该只获取20, 40, 60, 80, 100,因为第一个可观察对象具有数据.第二个可观察对象未运行,因为第一个可观察对象开始发出数据.

In the following example, I should get only 20, 40, 60, 80, 100 because the first observable has data. The second observable did not run because the first observable started emitting data.

推荐答案

可观察到的本地存储需要某种方式来表示没有数据.如果只是挂起"而从未完成,那么您可以使用计时器来完成它:

The local storage observable needs some way to signal that there is no data. If it just "hangs" and never completes, then you might use a timer to complete it:

// Use .amb() instead of .race() if your rxjs version is old
const timer = Observable.timer(1000).ignoreElements();
const lsObservable2 = Observable.race(lsObservable, timer);

这将启动一个计时器,如果可观察到的本地存储在1秒内未产生值,则它将结束流.

This will start a timer and if the local storage observable does not produce a value within 1s, it will end the stream.

如果没有数据,则可观察的本地存储将自行完成,那么您可以按原样使用它:

If your local storage observable will complete on its own if there is no data, then you can use it as is:

const lsObservable2 = lsObservable;

在这一点上,我们真的很想使用 Observable.defer .我们使用defer,以便每次有人订阅时,我们都可以创建一个新的闭包变量(hasValue),并监视可观察到的源是否为此订阅生成了一个值

At this point, we'd really like to use defaultIfEmpty, because that has the semantics you want. Unfortunately it only supports a scalar value for the default, when instead you want to yield a different observable stream. So lets write our own version of defaultIfEmpty which produces a new stream using Observable.defer. We use defer so that each time someone subscribes, we can create a new closure variable (hasValue) and monitor whether or not the source observable produces a value for this subscription

Observable.prototype.defaultObservableIfEmpty = function(defaultObservable) {
    const source = this;
    return Observable.defer(() => {
        let hasValue = false;
        // create a deferred observable that will evaluate to
        // defaultObservable if we have not seen any values, or
        // empty observable if we have seen any values.
        const next = Observable.defer(() => hasValue ? Observable.empty() : defaultObservable);

        // now use do() to set hasValue to true if we see a value from
        // the source observable
        const sourceSetsValue = source.do(v => hasValue = true);

        // now we can can just concat this sourceSetsValue
        // with out "next" observable.  When the first observable
        // finishes, it will subscribe to "next", which will then
        // either produce the defaultObservable or an empty observable
        return sourceSetsValue.concat(next);
    });
}

接下来,让我们假设您已将数据库Observable设置为在实际订阅之前不发出ajax调用.这是重要的一步.同样,您可以使用defer:

Next, let's assume you've setup your db Observable to not issue the ajax call until it is actually subscribed. This is an important step. Again you can use something like defer:

const dbObservable = Observable.defer(() => makeDbCall());

然后我们可以像这样使用您的新运算符:

Then we can use your new operator like so:

const data = lsObservable2.defaultObservableIfEmpty(dbObservable);

因此,您的应用程序代码如下所示(将新运算符添加到库中之后):

So your application code looks like this (once you've added the new operator to your library):

const timer = Observable.timer(1000).ignoreElements();
const lsObservable2 = Observable.race(lsObservable, timer);
const dbObservable = Observable.defer(() => makeDbCall());
const data = lsObservable2.defaultObservableIfEmpty(dbObservable);

这篇关于如果另一个可观察对象在RxJS中有数据,如何忽略所有可观察对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆