Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 带rxjs定时器的角度服务。。。需要主题吗?_Angular_Rxjs - Fatal编程技术网

Angular 带rxjs定时器的角度服务。。。需要主题吗?

Angular 带rxjs定时器的角度服务。。。需要主题吗?,angular,rxjs,Angular,Rxjs,我想实现一个全局下拉超时,用户可以将鼠标从下拉列表中移出,然后再回到下拉列表中,以防止它消失。我正在为此使用服务,但我不确定如何实现计时器 服务: 从'@angular/core'导入{Injectable}; 从“rxjs”导入{Observable,timer}; @可注射({providedIn:'root'}) 导出类DropTimerService{ dropHide$=新的可观察(); 构造函数(){} startTimer():void{ console.log('启动计时器')

我想实现一个全局下拉超时,用户可以将鼠标从下拉列表中移出,然后再回到下拉列表中,以防止它消失。我正在为此使用服务,但我不确定如何实现计时器

服务:

从'@angular/core'导入{Injectable};
从“rxjs”导入{Observable,timer};
@可注射({providedIn:'root'})
导出类DropTimerService{
dropHide$=新的可观察();
构造函数(){}
startTimer():void{
console.log('启动计时器')
this.dropHide$=计时器(3000);
}
stopTimer():void{
console.log('停止计时器')
this.dropHide$=新可观察();
}
}
启动和停止功能正在运行;控制台日志报告正确,但未触发对observable的订阅

this.dropSub=this.dropTimer.dropHide$.subscribe(事件=>{
console.log(事件)
this.dropClass='';
})
我想我需要一个
主题
。下一步
计时器上的主题,但我不确定。我还需要在用户将鼠标移回下拉列表时停止计时器,并希望能够使计时器在命令下立即过期(当用户打开其他下拉列表时,任何其他人都应收到关闭信号)


我觉得我可以用一些
setTimeout
s来实现这一点,它可以为
主题
。下一步
,但我也觉得可能有一种纯粹的rxjs方法来实现这一点。

上面编写的服务代码中的问题是,
dropHide$
成员变量将分配给新的
可观察的
实例。如果它获得了一个新实例,以前的订阅就会丢失。这就是为什么会发生以下情况:

  • dropHide$
    使用
    dropHide$=new Observable()获取默认的
    Observable
    实例
  • 在具有
    subscribe
    的组件中,我们订阅其事件
  • 当调用
    startTimer()
    时,this.dropHide$=timer(3000)
  • 将一个新的INSACE分配给
    dropHide$
    ,因此以前的
    subscribe
    的回调将永远不会被调用
  • 新实例化的
    Observable
    没有订阅,并且
    Observable
    是惰性的,因此事件永远不会触发
  • 为了解决这个问题,我提出了一个解决方案。 在
    服务
    中,我们存储
    订阅
    ,并在需要启动计时器时订阅。subscribe获取一个回调函数,该函数可以在计时器完成时调用。如果计时器被取消,我们只需取消订阅
    订阅
    。这样,
    服务
    代码如下所示:

    import { Injectable } from "@angular/core";
    import { Subscription, timer } from "rxjs";
    
    @Injectable({ providedIn: "root" })
    export class DropTimerService {
      private timerSubscription: Subscription;
    
      constructor() {}
    
      startTimer(timerDone: Function) {
        console.log("Starting the timer");
        this.timerSubscription = timer(3000).subscribe(event => {
          timerDone();
        });
      }
    
      stopTimer(): void {
        console.log("Timer stopped");
        this.timerSubscription.unsubscribe();
      }
    }
    
    组件模板示例:

    <p>
        Use the buttons to start/cancel the timer.
    </p>
    <button (click)="onStartClick()">Start</button> 
    <button (click)="onStopClick()">Cancel</button>
    
    要测试并使用它,这里有
    stackblitz
    代码:

    这几乎是我所需要的,但当我打开一个新的下拉列表时,它无法关闭所有其他下拉列表。目前,如果我打开一个新的,没有过期的旧的将保持打开状态,并且永远不会关闭,直到我将鼠标移入和移出它们。这就是为什么我认为我需要订阅一个主题,以便让下拉列表知道何时应该关闭。^通过在服务中添加一个主题来解决此问题,只需在每次勾选时关闭所有主题。
    import { Component } from "@angular/core";
    import { DropTimerService } from "./drop-timer.service";
    
    @Component({
      selector: "my-app",
      templateUrl: "./app.component.html",
      styleUrls: ["./app.component.css"]
    })
    export class AppComponent {
      name = "Angular";
    
      constructor(private dropTimerService: DropTimerService) {}
    
      onStartClick() {
        function TimerFinishedCallback() {
          console.log("Timer finished!");
        }
        this.dropTimerService.startTimer(TimerFinishedCallback);
      }
    
      onStopClick() {
        this.dropTimerService.stopTimer();
      }
    }