【问题标题】:Unable to subscribe the Subject data无法订阅主题数据
【发布时间】:2019-06-10 17:39:48
【问题描述】:

我正在使用共享服务通过主题发出数据。在一个组件中,我尝试订阅主题数据,但它从不订阅

我正在通过组件 A 中的主题发送索引数据,如下所示 组分A

export class ComponentA {
  onEditTestCase(index: number){
    this.sharedService.startedEditing.next(index);
  }
}

我正在使用共享服务通过主题发出索引数据。 shared.service.ts

import { Subject } from 'rxjs/Subject';

export class SharedService {

constructor(private sharedService: SharedService, private router: Router) {}

  startedEditing = new Subject<number>();
}

在组件 B 中,我尝试订阅,但它从不订阅。 B组份

import { Subscription } from 'rxjs';
export class ComponentB {
subscription: Subscription;

constructor(private router: Router, private sharedService: SharedService, 
  private route: ActivatedRoute) {}


ngOnInit() {
  this.subscription = this.sharedService.startedEditing
    .subscribe((index: number) => {
      this.editIndex = index;
      this.editMode = true;
      this.editedTestCase = this.sharedService.getTestCase(this.editIndex);
      this.testForm.setValue({
        testid: this.editedTestCase.testid,
        testPriority: this.editedTestCase.testPriority,
        testSummary: this.editedTestCase.testSummary
      });
    });
   }
 }

我在上面的代码中做错了吗?

【问题讨论】:

  • 您是否在两个组件中使用相同的 sharedService 实例?
  • 服务是单例吗?
  • 如何在组件 A 和组件 B 中创建服务实例?您向我们展示的服务没有 @Injectable 注释,并且您没有向我们展示组件的构造函数。
  • 我已经添加了构造函数代码。

标签: angular angular6 angular7


【解决方案1】:

尝试使用ReplaySubject 而不是Subject

尝试实现以下代码

common.setvice.ts

import { Injectable } from '@angular/core';
import {ReplaySubject} from 'rxjs/ReplaySubject';

@Injectable({
  providedIn: 'root'
})

export class CommonService {

  private startedEditing = new ReplaySubject<any>();
  public startedEditing$ = this.startedEditing.asObservable();
  constructor() { }

  setData(data) {
    this.startedEditing.next(data);
  }

}

a.component.ts

import { Component } from '@angular/core';
import { CommonService } from './common.service'

@Component({ templateUrl: 'a.component.html' })
export class AComponent {
    constructor( 
        private commonService: CommonService
     ) { }

    ngOnInit() {
        this.commonService.setData('data from component A');
    }
}

b.component.ts

import { Component } from '@angular/core';
import { CommonService } from './common.service'

@Component({ templateUrl: 'b.component.html' })
export class BComponent {
    constructor( 
        private commonService: CommonService
     ) { }

    ngOnInit() {
        this.commonService.startedEditing$.subscribe(data => {
            console.log(data); // this will print "data from component A";
        });
    }
}

如果上面的代码不清楚,请告诉我。

【讨论】:

  • 我不懂公共服务代码。我的代码中的“数据”与“startedEditing”相同吗? @raghul selvam
  • 是的!我用“startedEditing”变量更新了代码
  • 我使用了与您提到的相同的代码。在不发出数据的情况下,我尝试加载组件并对其进行订阅。当我发出一些数据时,它必须订阅吗?
  • 这是因为 BehaviorSubject 需要初始值来启动,这就是为什么我们在声明时传递“null”,我已经用“ReplaySubject”更新了代码,这不需要主动,现在检查并告诉我参考:stackblitz.com/edit/angular-qccvdp
  • 我使用了 ReplaySubject,在 CommonService 中调用了 setData 方法,但在组件 B 中再次没有被订阅。使用 Behavior Subject 订阅了它,但它有一个初始值。不知道现在出了什么问题
【解决方案2】:

将您的主题更改为私有属性,并使用属性获取器将主题作为可观察对象返回。 还要确保您使用的是同一个服务实例,将其定义为模块级别的提供者或父组件内的上一级提供者。

import { Subject } from 'rxjs/Subject';
export class SharedService {
private startedEditing = new Subject<number>();

public get StartEditing(): Observable<number> {
return this.startedEditing.asObservable();
}

【讨论】:

  • 返回 Subject 或 asObservable 有什么区别?
  • 逻辑上没有区别。它更干净,因为您阻止组件调用 next()
猜你喜欢
  • 1970-01-01
  • 2017-12-18
  • 2019-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-20
相关资源
最近更新 更多