Angular rxjs Subject : 在发出值后订阅一个主题
Angular rxjs Subject : subscribing to a subject after emitting values
我读了一篇 article,其中指出,如果您在事件已经发出时订阅主题,您将失去发出的值。他的演示示例如下。
let subject: Subject<string> = new Subject();
subject.next('test');
subject.subscribe((event) => {
console.log(event);
});
但是,我实现了类似的方法,其中第一个主题将发出值,然后订阅该主题。价值就在那里。没有丢失。代码如下。
在代码中,我们将身份验证信息保存在一个主题中。我们在 header 组件中使用它来显示注销按钮和链接。问题是为什么我的代码可以正常工作,即使文章说它不会?
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Subject} from "rxjs";
import { User } from "./user.model";
@Injectable({providedIn : "root"})
export class AuthService{
constructor(private httpClient:HttpClient){}
user = new Subject<User>(); //emit new user when login or logout or token expired
login(email:string,password:string){
return this.httpClient
.post<SignUpResponse>('https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=AIzaSyBCK9B2RcL0D4Bn8YaFCxE9rBXejTLNYQY',
{
email:email,
password:password,
returnSecureToken:true
})
.pipe(tap( response => this.handleAuthentication(response.email,response.idToken,response.idToken,response.expiresIn)))
}
private handleAuthentication(email:string,userId:string,token:string,expiresIn:string){
const expirationDate = new Date(new Date().getTime() + +expiresIn * 1000)
const user = new User(email,userId,token,expirationDate);
this.user.next(user);
}
}
Header.component.ts
import { Component,Output, EventEmitter, OnInit, OnDestroy } from "@angular/core";
import { Subscription } from "rxjs";
import { AuthService } from "../auth/auth/auth.service";
import { DataStorageService } from "../shared/data-storage.service";
@Component({
selector : 'app-header',
templateUrl:'./header.component.html'
})
export class HeaderComponent implements OnInit,OnDestroy{
collapsed = true;
private subscription : Subscription;
isAuthenticated : boolean = false;
constructor(private dataStorageService:DataStorageService,
private authService:AuthService){
}
ngOnInit(){
this.subscription = this.authService.user.subscribe( user => {
this.isAuthenticated = !!user;
console.log("User Object"); console.log(user);
console.log("IsAuthenticated value"); console.log(!!user);
})
}
ngOnDestroy(){
this.subscription.unsubscribe();
}
}
您的示例订阅 运行ning 的唯一原因是您在开始登录之前加载了 Header 组件 process/method。 ngOnInit
组件在服务中的 login
方法之前被调用。
您的代码 运行 与您在问题中描述的方式不同:
user = new Subject<User>();
subject.next('test');
// then this runs in component ngOnInit
this.authService.user.subscribe((event) => {
console.log(event);
});
// when you try to login from inside the component then it runs the login method with next.
login(email:string,password:string){.....
this.user.next(user); // now this is triggered hence you don't loose the user response.
我读了一篇 article,其中指出,如果您在事件已经发出时订阅主题,您将失去发出的值。他的演示示例如下。
let subject: Subject<string> = new Subject();
subject.next('test');
subject.subscribe((event) => {
console.log(event);
});
但是,我实现了类似的方法,其中第一个主题将发出值,然后订阅该主题。价值就在那里。没有丢失。代码如下。 在代码中,我们将身份验证信息保存在一个主题中。我们在 header 组件中使用它来显示注销按钮和链接。问题是为什么我的代码可以正常工作,即使文章说它不会?
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Subject} from "rxjs";
import { User } from "./user.model";
@Injectable({providedIn : "root"})
export class AuthService{
constructor(private httpClient:HttpClient){}
user = new Subject<User>(); //emit new user when login or logout or token expired
login(email:string,password:string){
return this.httpClient
.post<SignUpResponse>('https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=AIzaSyBCK9B2RcL0D4Bn8YaFCxE9rBXejTLNYQY',
{
email:email,
password:password,
returnSecureToken:true
})
.pipe(tap( response => this.handleAuthentication(response.email,response.idToken,response.idToken,response.expiresIn)))
}
private handleAuthentication(email:string,userId:string,token:string,expiresIn:string){
const expirationDate = new Date(new Date().getTime() + +expiresIn * 1000)
const user = new User(email,userId,token,expirationDate);
this.user.next(user);
}
}
Header.component.ts
import { Component,Output, EventEmitter, OnInit, OnDestroy } from "@angular/core";
import { Subscription } from "rxjs";
import { AuthService } from "../auth/auth/auth.service";
import { DataStorageService } from "../shared/data-storage.service";
@Component({
selector : 'app-header',
templateUrl:'./header.component.html'
})
export class HeaderComponent implements OnInit,OnDestroy{
collapsed = true;
private subscription : Subscription;
isAuthenticated : boolean = false;
constructor(private dataStorageService:DataStorageService,
private authService:AuthService){
}
ngOnInit(){
this.subscription = this.authService.user.subscribe( user => {
this.isAuthenticated = !!user;
console.log("User Object"); console.log(user);
console.log("IsAuthenticated value"); console.log(!!user);
})
}
ngOnDestroy(){
this.subscription.unsubscribe();
}
}
您的示例订阅 运行ning 的唯一原因是您在开始登录之前加载了 Header 组件 process/method。 ngOnInit
组件在服务中的 login
方法之前被调用。
您的代码 运行 与您在问题中描述的方式不同:
user = new Subject<User>();
subject.next('test');
// then this runs in component ngOnInit
this.authService.user.subscribe((event) => {
console.log(event);
});
// when you try to login from inside the component then it runs the login method with next.
login(email:string,password:string){.....
this.user.next(user); // now this is triggered hence you don't loose the user response.