简体   繁体   English

为什么主题订阅在 Angular 9 中不起作用

[英]Why Subject subscribe is not working in Angular 9

I have a Subject defined in the authentication service.我在身份验证服务中定义了一个主题。 When I want to move user information to another component, subscribe doesn't work and it doesn't work.当我想将用户信息移动到另一个组件时,订阅不起作用,它也不起作用。 I tried to use it in different hooks, but again it was useless.我尝试在不同的钩子中使用它,但它又没用。 I also used BehaviorSubject, but null returns.我也使用了 BehaviorSubject,但 null 返回。

Does anyone know what the problem is?有谁知道问题是什么?

auth.service.ts auth.service.ts

import {Injectable} from '@angular/core';
import {HttpClient, HttpErrorResponse, HttpHeaders} from '@angular/common/http';
import {AuthModel} from '../Infrastructure/Models/authModel';
import {RegisterUserDeviceModel} from '../Infrastructure/Models/RegisterUserDeviceModel';
import {ResponseModel} from '../Infrastructure/Models/responseModel';
import {RegisterUserDeviceResponseModel} from '../Infrastructure/Models/registerUserDeviceResponseModel';
import {LoginResponseModel} from '../Infrastructure/Models/LoginResponseModel';
import {RegisterDeviceDataMosel} from '../app.component';
import {BehaviorSubject, Subject, throwError} from 'rxjs';
import {UserDataModel} from '../Infrastructure/Models/UserDataModel';
import {catchError, tap} from 'rxjs/operators';
import {RoleEnum} from '../Infrastructure/Enums/RoleEnum';

@Injectable({
    providedIn: 'root'
})
export class AuthService {
    devicecode: string = (<RegisterDeviceDataMosel> JSON.parse(localStorage.getItem('RegisterDeviceData'))).devicecode;
    user = new Subject<UserDataModel>();

constructor(private _http: HttpClient) {
}

Signin(data: AuthModel) {
    let _headers = new HttpHeaders();
    _headers = _headers.append('Content-Type', 'application/json');
    _headers = _headers.append('Access-Control-Allow-Origin', '*');
    _headers = _headers.append('X-Skip-Interceptor', '');
    _headers = _headers.append('device_code', this.devicecode);
    const _options = {headers: _headers};

    return this._http.post<ResponseModel<LoginResponseModel>>('http://localhost:5000/account/login', data, _options)
        .pipe( catchError(this.handelError) , tap(resData => {
            this.handleAuth(data.username, resData.response.access_token, resData.response.refresh_token
                , resData.response.role, resData.response.expires_in);
        }));
}

AutoLoading(): boolean {
    debugger;
    const userData: {
        username: string,
        access_token: string,
        refresh_token: string,
        role: RoleEnum,
        _tokenexpirationDate: string
    } = JSON.parse(localStorage.getItem('userData'));
    if (!userData) {
        return false;
    }
    const loadUser = new UserDataModel(userData.username, userData.access_token, userData.refresh_token
        , userData.role, new Date(userData._tokenexpirationDate));
    if (loadUser.token) {
        this.user.next(loadUser);
        return true;
    }
}

private handleAuth(username, token, refresh_token, role, expiresin) {
    const expirationDate = new Date(new Date().getTime() + +expiresin * 60000);
    const user = new UserDataModel(username, token, refresh_token
        , role, expirationDate);
    debugger;
    this.user.next(user);
    localStorage.setItem('userData', JSON.stringify(user));
}

private handelError(errorResponse: HttpErrorResponse){
    return throwError(errorResponse);
}
}

component零件

import {AfterViewChecked, AfterViewInit, Component, OnDestroy, OnInit} from '@angular/core';
import * as momenthijri from 'moment-hijri';
import {AuthService} from '../../auth/auth.service';
import {Subscription} from 'rxjs';



@Component({
  selector: 'app-footer',
  styleUrls: ['./footer.component.scss'],
  templateUrl: './footer.component.html',
  providers: [AuthService]
})
export class FooterComponent implements OnInit , OnDestroy {
  private userSub: Subscription ;
  nowDate = new Date();
  hijri;
  public userName;
  public role;

  constructor(private authService: AuthService) {
  }

  ngOnInit(): void {
    this.hijri = momenthijri(this.nowDate.toString()).format('iYYYY/iM/iD');
    this.userSub = this.authService.user.subscribe( res =>{
      debugger;
      this.userName = res.username ;
      this.role = res.role;
    });
  }

  ngOnDestroy(): void {
    this.userSub.unsubscribe();
  }
}

Thank you all for your help谢谢大家的帮助

It happens because Subject doesn't store the data inside and you have to subscribe before providing the data in your subject.发生这种情况是因为Subject没有将数据存储在里面,并且您必须先订阅才能在您的主题中提供数据。 Also, you can use BehaviorSubject that stores the data inside, and all the time you subscribe to it you will receive this data, but you have to provide an initial value.此外,您可以使用BehaviorSubject将数据存储在其中,并且在您订阅它的所有时间都会收到此数据,但您必须提供初始值。

On the other hand, you can simulate BehaviorSubject without initial value by user = new ReplaySubject<UserDataModel>(1) which will store the last data and return it every time you subscribe.另一方面,您可以通过user = new ReplaySubject<UserDataModel>(1)模拟没有初始值的BehaviorSubject ,它将存储最后的数据并在每次订阅时返回。 Hope, my explanations is clear:)希望,我的解释很清楚:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM