Angular2 (rc1) observables 似乎没有工作

Angular2 (rc1) observables do not appear to be working

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

我做了以下事情:

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

我的服务:

@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 设置一些信息时,我的控制台从不打印我用 console.log(data)

在 ComponentB 中输入的内容

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

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

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

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

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

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

@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,即 returns 一个 Observable 序列,从而隐藏了源序列。一个组件 (B) 可以订阅此序列并获取最后设置的值和后续值,因为您使用的是 BehaviourSubject 而不是 Subject。