【问题标题】:How to set value to globle variable in Subscribe method's value in Angular Rxjs如何在Angular Rxjs的订阅方法值中为全局变量设置值
【发布时间】:2021-05-07 03:18:05
【问题描述】:

我想知道如何从 subscribe 方法中取出值并将其设置为全局变量。所以我可以在我的打字稿文件的任何地方使用它

    constructor(
        private VNFCInstanceServicesService: VNFCInstanceServicesService,
    ) {
        this.siteId = this.route.snapshot.queryParams.siteId;
        this.vnfInsId = this.route.snapshot.queryParams.vnfInstanceId;
        this.VNFCInstanceServicesService.filterVnfciServices(
            this.vnfInsId,
            this.siteId,
            0
        ).subscribe((data) => {
            this.source.load(data.payload.records);
        });
   }

我需要把这个(data.payload.records)作为一个全局变量值

【问题讨论】:

  • 不能同步使用异步数据。任何直接依赖于 observable 数据的语句都必须在订阅中。换句话说,您需要在需要响应的地方订阅。但是,您可以使用 shareReplay 运算符或 ReplaySubject mutli-cast observable 来研究缓存机制。

标签: javascript angular typescript rxjs


【解决方案1】:

我认为学习如何设计一个可观察到的流,它可以准确地发出您需要的数据,这对您最有帮助。一般来说,当订阅数量和本地命令式“状态”变量最少时,代码会简单得多。

而不是做这样的事情:

class SomeComponent {
  private siteId;
  private vnfInsId;
    
  constructor(
    private route: ActivatedRoute,
    private service: VNFCInstanceServicesService
  ) {
    this.siteId = this.route.snapshot.queryParams.siteId;
    this.vnfInsId = this.route.snapshot.queryParams.vnfInstanceId;
    this.service.filterVnfciServices(
      this.vnfInsId,
      this.siteId,
      0
    ).subscribe((data) => {
      this.source.load(data.payload.records);
    });
  }
}

您只能使用可观察对象。 RxJS 提供了许多操作符和静态函数,允许您从彼此构建可观察的流。

class SomeComponent {
  private siteId$   = this.route.paramMap.pipe(map(params => params.get('siteId')));
  private vnfInsId$ = this.route.paramMap.pipe(map(params => params.get('vnfInstanceId')));

  public records$  = combineLatest([this.siteId$, this.vnfInsId$]).pipe(
    switchMap(([siteId, vnfInsId]) => this.service.filterVnfciServices(vnfInsId, siteId, 0)),
    switchMap(data => this.source.load(data.payload.records))
  );

  constructor(
    private route: ActivatedRoute,
    private service: VNFCInstanceServicesService
  ) { 
    this.records$.subscribe(
      records => console.log('records: ', records)
    )
  }
}

使用的运算符:

  • map 用于siteId$vnfInsId$ 的定义中,以简单地从路由的参数映射中返回相关键。
  • combineLatest 接受多个可观察源,并在其中任何一个发出时发出一个包含其最新值的数组。
  • switchMap 接收combineLatest 发出的数组,并从您对filterVnfciServices() 的调用中形成一个“内部可观察”。它将从此“内部可观察”订阅一个发射值。
  • 第二个switchMap 接收来自filterVnfciServices() 的发射并使用它来调用source.load(),然后发射该结果。

这种响应式方法的巧妙之处在于,每当任何源发出新值时,依赖于它们的可观察对象将自动接收更新后的值。

我承认,在您充分掌握这些函数/运算符的工作原理之前,使用完全反应式代码的价值并没有完全实现,但是一旦您掌握了......代码就会变得更加简洁。

【讨论】:

    【解决方案2】:

    因为你是在一个类的上下文中(根据显示的构造函数判断),你也可以在那个对象上添加一个属性,然后给它赋值:

    ...
    private records: any;
    constructor(
      private VNFCInstanceServicesService: VNFCInstanceServicesService,
    ) {
        this.siteId = this.route.snapshot.queryParams.siteId;
        this.vnfInsId = this.route.snapshot.queryParams.vnfInstanceId;
        this.VNFCInstanceServicesService.filterVnfciServices(
        this.vnfInsId,
        this.siteId,
        0
        ).subscribe((data) => {
           this.source.load(data.payload.records);
           this.records = data.payload.records;
        });
    }
    
    private randomFn() {
      // can access your data here
      console.log(this.records);
    }
    

    这将使记录在类的上下文中可用,如果您在其他地方需要它,您可以在类实例上公开它。或者,您也可以将其设置在全局对象上,这是不鼓励,会导致很多问题。

    【讨论】:

    • 我已经尝试过这个 btw 它不起作用控制台说它未定义
    • 如果在订阅块运行后调用randomFn,那么您应该会在console.log 中看到值。如果在此之前调用它,你会得到undefined
    猜你喜欢
    • 1970-01-01
    • 2014-06-18
    • 1970-01-01
    • 1970-01-01
    • 2020-10-28
    • 2021-01-28
    • 2021-02-15
    • 1970-01-01
    • 2019-09-15
    相关资源
    最近更新 更多