javascript - 如果另一个可观察量在 RxJS 中有数据,如何忽略一个可观察量中的所有数据?

标签 javascript rxjs observable

我有两个可观察对象,一个从浏览器本地存储接收数据,另一个通过WebAPI数据库接收数据。

  1. 我想订阅它们,因此如果本地存储中的可观察对象有数据,则不要启动从数据库获取数据的观察对象。
  2. 如果 localstorage 中的可观察对象没有任何 data,调用ajax调用从WebAPI获取数据。

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

enter image description here

最佳答案

本地存储可观察对象需要某种方式来表明没有数据。如果它只是“挂起”并且从未完成,那么您可以使用计时器来完成它:

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

这将启动一个计时器,如果本地存储 observable 在 1 秒内没有产生值,它将结束流。

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

const lsObservable2 = lsObservable;

此时,我们真的很想使用defaultIfEmpty ,因为它具有您想要的语义。不幸的是,当您想要生成不同的可观察流时,它仅支持默认标量值。那么让我们编写我们自己的 defaultIfEmpty 版本它使用 Observable.defer 生成一个新流。我们使用defer这样每次有人订阅时,我们都可以创建一个新的闭包变量( hasValue )并监视源可观察对象是否为该订阅生成值

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);
    });
}

接下来,假设您已将 db Observable 设置为在实际订阅之前不发出 ajax 调用。这是重要的一步。同样,您可以使用类似 defer 的内容。 :

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

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

const data = lsObservable2.defaultObservableIfEmpty(dbObservable);

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

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

关于javascript - 如果另一个可观察量在 RxJS 中有数据,如何忽略一个可观察量中的所有数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43151520/

相关文章:

根据先前的结果订阅多个 http 请求的 Angular RxJS 最佳实践

javascript - 通过服务从 json 文件中获取数据在 Angular4 中给出 "unexpected end of input"

javascript - 仅更改一个值并保持其他完整 Redux

JavaScript优化: Caching math functions globally

javascript - angularjs:如何访问指令(文本)值

javascript - 如何判断 RxJS 的版本号

angular - 如何更改可观察对象的属性。 Angular 2/行为主题

observable - takeFirst 方法的替代方法是什么

javascript - KnockoutJS Observable 未在模板中更新

php - 如何检测鼠标光标在div中的位置