【问题标题】:Resume video if user is inactive/idle for 30 seconds (RxJs)如果用户处于非活动/空闲状态 30 秒 (RxJs),则恢复视频
【发布时间】:2021-12-29 06:50:40
【问题描述】:

让我稍微解释一下功能。我的目标是当视频正在播放时,如果用户点击视频,它将被暂停,然后他可能会在此过程中做一些事情。同时,我需要检测用户是否空闲 30 秒。如果是这样,则再次自动恢复视频。

我已经使用 javascript 基本 setTimeout 功能实现了。下面分享一下代码

@HostListener('window:click', ['$event'])
onClick: (event) => {
    // stop the video
    this.activity = setTimeout(() => { /* resume */ } , 30000)
}


@HostListener('window:mousemove', ['$event'])
onMouseMove: (event) => {
    clearTimeout(this.activity)
    this.activity = setTimeout(() => { /* resume */ } , 30000)
}

有什么建议可以使用RxJs 方式解决这个问题吗?

【问题讨论】:

    标签: javascript angular typescript events rxjs


    【解决方案1】:
    activity = new Subject<void>();
    
    @HostListener('window:click', ['$event'])
    onClick(event: any) {
        // stop the video
        interval(30000).pipe(takeUntil(this.activity)).subscribe(() => {
            /* resume */
            this.activity.next();
            this.activity.complete();
        });
    }
    
    
    @HostListener('window:mousemove', ['$event'])
    onMouseMove(event: any) {
        this.activity.next();
        this.activity.complete();
    
        this.activity = new Subject<void>();
    
        interval(30000).pipe(takeUntil(this.activity)).subscribe(() => {
            /* resume */
            this.activity.next();
            this.activity.complete();
        });
    }
    

    【讨论】:

      【解决方案2】:

      这是我想出的:

      它在 Angular Zone 之外运行。当鼠标移动时,不会给您的应用程序带来变化检测的负担。它仅在视频停止或继续时触发变化检测。

      import { DOCUMENT } from '@angular/common';
      import { Inject, Injectable, NgZone } from '@angular/core';
      import {
        BehaviorSubject,
        fromEvent,
        merge,
        Observable,
        of,
        Subject,
      } from 'rxjs';
      import {
        distinctUntilChanged,
        mapTo,
        startWith,
        switchMapTo,
        debounceTime,
        takeUntil,
      } from 'rxjs/operators';
      
      @Injectable({ providedIn: 'root' })
      export class VideoService {
        private readonly onDestroy = new Subject<void>();
        readonly isPlaying$: Observable<boolean> = new BehaviorSubject(true);
      
        constructor(
          @Inject(DOCUMENT) private readonly document: Document,
          private readonly ngZone: NgZone
        ) {
          // Run the whole logic outside of angular, so it won't burdent the app
          this.ngZone.runOutsideAngular(() => {
            fromEvent(this.document, 'click', { passive: true })
              .pipe(
                // On every click we create a merge observable, and unsubscribe from the previous one if exists
                switchMapTo(
                  // We merge two observables
                  merge(
                    // one that sets the playing to false instantly
                    of(false),
                    // Subscribe to the documents mousemove
                    fromEvent(this.document, 'mousemove', { passive: true }).pipe(
                      // we start the stream with a value, so after the clicking it will go back to playing without moving the cursor.
                      startWith(null),
                      // With debounceTime we wait for no mousemove
                      debounceTime(1000),
                      // All values are mapped to true
                      mapTo(true)
                    )
                  )
                ),
                distinctUntilChanged(),
                takeUntil(this.onDestroy)
              )
              .subscribe((value) =>
                // when we get a different value run it in the zone, so Angular will know to run change detection.
                this.ngZone.run(() => {
                  (this.isPlaying$ as BehaviorSubject<boolean>).next(value);
                })
              );
          });
        }
      
        ngOnDestroy() {
          this.onDestroy.next();
          this.onDestroy.complete();
        }
      }
      

      Running example

      我对其他解决方案感兴趣,因为我的解决方案似乎并不简单。我觉得它也可以做得更简单。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-16
        • 1970-01-01
        • 1970-01-01
        • 2020-06-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-11
        相关资源
        最近更新 更多