gpt4 book ai didi

angular - RxJS 6 页面不活动时暂停或缓冲可观察

转载 作者:搜寻专家 更新时间:2023-10-30 21:25:30 25 4
gpt4 key购买 nike

所以我有一个流,比方说字母,我需要所有字母按正确的顺序将它们组合成一个词。一切正常,直到用户更改选项卡、最小化浏览器或切换应用程序 - 行为几乎与我使用 setTimeout() 相同 - 弄乱了订单,丢失了元素等。我试图实现我的目标是使用 bufferWhen()bufferToggle()takeUntil()publish()connect() 但没有成功。我也考虑过使用 delayWhen,但它已被弃用并且可能不适合,因为它会立即停止流。我应该使用哪些功能以及如何使用?这是我的代码:

export class MyComponent implements AfterViewInit {
private visibilityChange$ = fromEvent(document, 'visibilitychange').pipe(startWith('visible'), shareReplay({ refCount: true, bufferSize: 1 }));
private show$ = this.visibilityChange$.pipe(filter(() => document.visibilityState === 'visible'));
private hide$ = this.visibilityChange$.pipe(filter(() => document.visibilityState === 'hidden'));

public ngAfterViewInit() {
const lettersStream$ = zip( // add delay for each letter
from(['w', 'o', 'r', 'd']),
interval(1000))
// pause when hide$ fires, resume when show$
.pipe(map(([letter, delayTime]) => letter))
.subscribe(console.log);
}
}

我在 stackblitz 上做了一个演示 - 我想要的就是看到(在标签不活动时停止写作)如何写在屏幕上。

最佳答案

因为我在我的 RxJS Snake Game 中做了类似的暂停/取消暂停操作, 我会帮助你举个例子。

想法是有一个 interval(1000) 作为真实来源,这意味着一切都将基于它。因此,基于我们需要停止在可见性隐藏时发出事件并在可见性显示时继续发出事件这一事实,我们的目标变成了使此间隔可暂停。最后,为了让事情变得更简单,我们可以在可见性隐藏时停止收听源间隔,并在可见性显示到来时再次开始收听。现在让我们来看看具体的实现:

您也可以在 RxJS Pause Observable 上使用修改后的 StackBlitz 演示代码.

import { of, interval, fromEvent, timer, from, zip, never } from 'rxjs';
import { delayWhen, tap, withLatestFrom, concatMap, take, startWith, distinctUntilChanged, switchMap, shareReplay, filter, map, finalize } from 'rxjs/operators';

console.log('-------------------------------------- STARTING ----------------------------')

class MyComponent {
private visibilityChange$ = fromEvent(document, 'visibilitychange')
.pipe(
map(x => document.visibilityState),
startWith('visible'),
shareReplay(1)
);

private isVisible$ = this.visibilityChange$.pipe(
map(x => x === 'visible'),
distinctUntilChanged(),
);

constructor() {
const intervalTime = 1000;
const source$ = from('word or two'.split(''));
/** should remove these .pipe(
concatMap(ch => interval(intervalTime).pipe(map(_ => ch), take(1)))
);*/

const pausableInterval$ = this.isVisible$.pipe(
switchMap(visible => visible ? interval(intervalTime) : never()),
)

const lettersStream$ = zip(pausableInterval$, source$).pipe(
map(([tick, letter]) => letter),
).subscribe(letter => {
this.writeLetter(letter);
});
}

private writeLetter(letter: string) {
if (letter === ' ') letter = '\u00A0'; // fix for spaces
document.body.innerText += letter;
}
}

const component = new MyComponent();

这是来自 StackBlitz 的确切代码,我复制到这里是为了更好地为您解释。

现在让我们为您分解有趣的部分:

  1. 查看 visibilityChange$isVisible$。它们稍作修改,因此第一个发出基于 document.visibilityState 的字符串值 'visible''hidden'。当 document.visibilityState 等于 'visible' 时,第二个发出 true。

  2. 查看source$。它将发出一个字母,然后在 concatMapinterval 的帮助下等待 1 秒,并使用 take(1) 执行此过程,直到有文本中没有剩余字符。

  3. 看看pausableInterval$。基于将根据 document.visibilityState 更改的 this.isVisible$,我们的 pausableInterval$ 将每秒发射项目或不会发射由于 never() 而导致的任何事情。

  4. 最后看看 lettersStream$。在 zip() 的帮助下,我们将压缩 pausableInterval$source$,因此我们将从 source 中获取一个字母,从暂停间隔。如果 pausableInterval$ 由于可见性变化而停止发射,zip 也会等待,因为它需要两个 Observable 一起发射才能将事件发送到订阅者。

关于angular - RxJS 6 页面不活动时暂停或缓冲可观察,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57020431/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com