Angular2 (rc1) observables 似乎没有工作
Angular2 (rc1) observables do not appear to be working
我想要两个具有 2 条不同路由的不同组件,我想将信息从组件 A 传递到组件 B。
我做了以下事情:
- 创建处理事件的服务
- 在 componentA 设置信息并传递给服务事件
- 尝试在 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。
我想要两个具有 2 条不同路由的不同组件,我想将信息从组件 A 传递到组件 B。
我做了以下事情:
- 创建处理事件的服务
- 在 componentA 设置信息并传递给服务事件
- 尝试在 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)
如果您在每个组件上提供服务,您就不会获得共享服务。每个组件都有自己的服务实例。
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。