angular - 如果可观察对象正在进行中,则订阅它,如果没有,则重新启动它

标签 angular typescript rxjs

如果我有一个需要很长时间才能执行的可观察对象。我们将其称为longObservable,它是Observable类型,执行需要5秒,并且每次执行时只发出一个新字符串一次,然后完成。

longObservable(): Subject<string> {
    return timer(5000).pipe{
        map(() => randomString())
    }
}

还有一些其他页面多次调用它。如果正在进行中,我想继续这一过程。如果完成了,我想重新开始。

longObservable.subscribe() // Immediate, start the timer

两秒后运行:

longObservable.subscribe() // Get the same string as
                            //  the above subscription in 3 seconds.

20 秒后运行

longObservable.subscribe() // Start a new iteration and wait
                            // 5 seconds, get a new string.

我认为第二个订阅很简单,它会按照我想要的方式工作。这是我遇到麻烦的第三个。由于 longObservable 完成,它将立即发出与其他两个相同的值。

这用于设备上的地理定位。我想请求一个新位置,但如果已经有一个请求正在进行中,则只需使用该结果。

编辑:将 observable 更改为多播主题,删除 take(1)。

编辑2:https://stackblitz.com/edit/angular-venpk4这是我想要的一个工作示例。我希望在没有timerRunning 变量和RxJS 运算符的情况下完成此任务。它位于 hello 组件下并打印到控制台。

最佳答案

棘手的问题。这是我在 StackBlitz 中的解决方案。实现此目的的几个关键是 share() 运算符,它可以有效地将可观察对象转换为主题,而无需显式声明主题。但是,一旦旧订阅完成,您需要使用新订阅创建一个新主题,因此我创建了一个工厂函数来返回现有的可共享 Observable(如果 longObservable() 仍在进行中)否则生成一个新的。

以下是 StackBlitz 中的重要内容:

let inProgress: boolean = false;

function longObservable(): Observable<string> {
    return timer(5000).pipe(
        map(() => randomString()),
        tap(() => inProgress = false),
        share()
    )
}

let obs$: Observable<string>;

function getLongObs(): Observable<string> {
    if (inProgress) {
        return obs$
    } else {
        inProgress = true;
        obs$ = longObservable();
        return obs$;
    }
}

console.log('initiate first subscribe');
getLongObs().subscribe(
    rand => console.log(`First subscribe returned ${rand}`)
);

setTimeout(() => {
    console.log('initiate second subscribe');
    getLongObs().subscribe(
        rand => console.log(`Second subscribe returned ${rand}`)
    );
}, 2000);

setTimeout(() => {
    console.log('initiate third subscribe');
    getLongObs().subscribe(
        rand => console.log(`Third subscribe returned ${rand}`)
    );
}, 7000)

希望这会有所帮助!

关于angular - 如果可观察对象正在进行中,则订阅它,如果没有,则重新启动它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54136646/

相关文章:

Angular 5 HttpClient 文件上传 - 处理多部分表单边界

javascript - 基于子组件的父组件的 Angular 显示/隐藏

javascript - 为什么 protected 成员可以被 TypeScript 中的公共(public)成员覆盖?

javascript - RxJs5 在没有运动时发出信号

javascript - RxJS(和 Angular ): Attempting to cache one-time HTTP requests still causes multiple requests

javascript - 如何让systemjs从全局格式的CDN加载模块?

TypeScript Compiler API 在转换过程中丢失格式

angular - 使用 Firebase 身份验证使用户 session 过期

angular - 使用异步管道在单个 ngIf 上组合两个或多个( bool )可观察量

Angular 将父组件的多个服务实例用于子组件