【问题标题】:Angular2 (rc1) observables do not appear to be workingAngular2 (rc1) observables 似乎没有工作
【发布时间】:2016-09-09 21:43:19
【问题描述】:

我想要两个具有 2 条不同路由的不同组件,我想将信息从组件 A 传递到组件 B。

我做了以下事情:

  1. 创建处理事件的服务
  2. 在componentA设置信息并传递给Service事件
  3. 尝试在组件 B 处获取此信息

我的服务:

@Injectable()
export class TokenService{
private tokenSource = new Subject<Object>();
token$ = this.tokenSource.asObservable();

setToken(token: string) {
  this.tokenSource.next(token);
}

组件A:

@Component({
selector: 'login',
templateUrl: './login.html',
providers: [TokenService],
moduleId: module.id
})

export class LoginCmp {
   constructor(private tokenService: TokenService) {
}

someMethod() {
    this.tokenService.setToken('some dynamic value');
}
....

组件B:

@Component({
selector: 'cabecalho',
moduleId: module.id,
templateUrl: './cabecalho.html',
providers: [TokenService]
})

constructor(private tokenService: TokenService) {
tokenService.token$.subscribe(
  data => {
    console.log(data);

  });
}

当我从 ComponentA 设置一些信息时,我的控制台从不打印我在 ComponentB 中使用console.log(data) 放置的内容

【问题讨论】:

  • 两个组件在同一个 NgModule 中吗?尝试在我们的 NgModule 中注册服务,而不是在两个组件中使用 providers 数组。
  • @candidJ RC1 没有 NgModule
  • 不会出现错误吗?我建议你更新到rc6

标签: events angular observable angular2-services


【解决方案1】:

首先,您的组件使用不同的 TokenService 实例。您需要在他们之间使用共享服务。

其次,componentB 仅在 在 componentA 中设置之后才订阅 Subject。如果您在设置值时没有订阅主题,那么您将不会获得该值。如果您打算在订阅之前设置值,您应该使用 BehaviourSubject。订阅 BehaviourSubject 将允许您接收设置的最后一个值以及后续值。

第三,使用 asObservable 意味着您不希望能够获取 tokenSource 的值。但是,您有一个功能可以做到这一点,并且可以从 componentB 访问。我建议将 tokenSource 设置在一个单独的服务中,该服务将在 ComponentA 和 tokenService 之间共享。

您可以尝试以下方法。创建共享服务:

@Injectable()
export class SharedService {
    tokenSource = new BehaviorSubject<Object>('initial value');

    setToken(token: string) {
        this.tokenSource.next(token);
    }
}

在您的 AppComponent 引导程序函数中初始化 SharedService 的共享实例。

bootstrap(AppComponent, [ SharedService ]);

创建一个令牌服务。将 SharedService 的实例传递给 TokenService 的构造函数(不要将 SharedService 添加到 [providers],因为它会创建一个新实例):

@Injectable()
export class TokenService {
    token$: any;
    constructor(sharedService: SharedService) {
        this.token$ = sharedService.tokenSource.asObservable();
    }

ComponentA(同样,不要在 [providers] 中指定 SharedService。因此 Angular2 将向上搜索层次结构,直到找到 SharedService 的实例。)

@Component({
    selector: 'compA',
    templateUrl: '/compA.html',
})

export class ComponentA {
    constructor(private sharedService: SharedService){
        console.log('CompA');
        this.sharedService.setToken('some dynamic value');
    }
}

ComponentB 创建一个新的 TokenService 实例。

@Component({
    selector: 'compB',
    templateUrl: '/compB.html',
    providers: [TokenService]
})

export class ComponentB implements OnDestroy {
    sub: any;
    constructor(private tokenService: TokenService) {
        console.log('CompB');
        this.sub = tokenService.token$.subscribe(
            data => {
                console.log(data);
            });
    }

    ngOnDestroy() {
        if (this.sub)
            this.sub.unsubscribe();
    }
}

因此,您有一个共享服务来公开您的 tokenSource 值。还有一个 tokenService,它返回一个 Observable 序列,从而隐藏了源序列。还有一个组件 (B) 可以订阅此序列并获取设置的最后一个值和后续值,因为您使用的是 BehaviourSubject 而不是 Subject。

【讨论】:

  • 非常感谢您,现在我明白了我的问题!
【解决方案2】:

如果您在每个组件上提供服务,您就不会获得共享服务。每个组件都有自己的服务实例。

Angular2 为每个提供者维护一个实例。如果您在共享父组件上提供服务(最终共享父组件为AppComponent)或将其传递给bootstrap(AppComponent, [TokenService]),那么它们将获得相同的实例注入。

【讨论】:

  • 谢谢你的解释很重要
猜你喜欢
  • 2013-11-25
  • 2017-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-25
相关资源
最近更新 更多