首页 > 解决方案 > Angular rxjs主题:在发出值后订阅主题

问题描述

我读过一篇文章,其中指出,如果您在事件已经发出时订阅主题,您将丢失发出的值。他的演示示例如下。

let subject: Subject<string> = new Subject();
subject.next('test');
 
subject.subscribe((event) => {
  console.log(event);
});

但是,我实现了类似的方法,其中第一个主题将发出值,然后订阅主题。价值就在那里。没有丢失。代码如下。在代码中,我们将身份验证信息保存在主题中。我们在标题组件中使用它来显示注销按钮和链接。问题是为什么我的代码可以工作,即使文章说它不会?

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);
    }
}

头文件.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();
    }
}

输出

标签: javascriptangularrxjsobservablesubject

解决方案


您的示例订阅正在运行的唯一原因是因为您在启动登录过程/方法之前加载了 Header 组件。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.

推荐阅读