[英]How to use Ionic Data Storage with BehaviorSubject and Observable
I'm trying to create app with Angular 9 / Ionic 5我正在尝试使用 Angular 9 / Ionic 5 创建应用程序
I'm using Ionic Data Storage我正在使用离子数据存储
So, my auth.service.ts looks like:所以,我的auth.service.ts看起来像:
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Storage } from '@ionic/storage'
import { BehaviorSubject, Observable, from } from 'rxjs'
@Injectable({
providedIn: 'root'
})
export class AuthService {
private currentTokenSubject: BehaviorSubject<string>
public currentToken: Observable<string>
constructor(
private http: HttpClient,
private storage: Storage,
) {
this.getToken()
.then(res => {
this.currentTokenSubject = new BehaviorSubject(res)
this.currentToken = this.currentTokenSubject.asObservable()
}
)
}
async getToken() {
return await this.storage.get('accessToken')
}
public get currentTokenValue(): string {
return this.currentTokenSubject.value;
}
login(username: string, password: string) {
const headers = new HttpHeaders({
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Basic ' + btoa(username + ':' + unescape(encodeURIComponent(password)))
})
return this.http.post<Token>(`${environment.apiUrl}/auth/signin`, { }, { headers })
.pipe(map((res: Token) => {
let token = res.token
// store user details and jwt token in local storage to keep user logged in between page refreshes
this.storage.set('accessToken', token);
return token;
}));
}
logout() {
// remove user from local storage to log user out
this.storage.remove('accessToken');
this.currentTokenSubject.next(null);
}
}
and jwt.interceptor.ts looks like:和jwt.interceptor.ts看起来像:
import { Injectable } from '@angular/core'
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'
import { Observable } from 'rxjs'
import { AuthService } from '@app/_services'
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(
private authService: AuthService
) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// add authorization header with jwt token if available
const currentToken = this.authService.currentTokenValue;
if (currentToken) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${currentToken}`
}
});
}
return next.handle(request);
}
}
So, when I try to call service, I get error, because Ionic Storage returns Observable:所以,当我尝试调用服务时,我得到了错误,因为 Ionic Storage 返回 Observable:
Error: Uncaught (in promise): TypeError: Cannot read property 'value' of undefined
TypeError: Cannot read property 'value' of undefined
at AuthService.get currentTokenValue [as currentTokenValue] (auth.service.ts:39)
Question is: What is the proper way to get value from Ionic Storage and use it?问题是:从 Ionic Storage 获取价值并使用它的正确方法是什么?
The issue you are trying to access the BehaviorSubject
's value
getter before it is assigned any values.您在为其分配任何值之前尝试访问
BehaviorSubject
的value
获取器的问题。 It is best to avoid the value
getter and subscribe to the observable to keep things asynchronous.最好避免使用
value
getter 并订阅 observable 以保持异步。 Try the following尝试以下
auth.service.ts auth.service.ts
export class AuthService {
private currentTokenSubject = new BehaviorSubject<string>(null); // <-- assign default value here
constructor(
private http: HttpClient,
private storage: Storage,
) {
this.getToken().then(
res => {
this.currentTokenSubject.next(res); // <-- push token to the observable
}
);
}
async getToken() {
return await this.storage.get('accessToken');
}
public get currentTokenValue(): Observable < string > {
return this.currentTokenSubject.asObservable(); // <-- return observable here
}
login(username: string, password: string) {
const headers = new HttpHeaders({
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Basic ' + btoa(username + ':' + unescape(encodeURIComponent(password)))
})
return this.http.post<Token>(`${environment.apiUrl}/auth/signin`, {}, { headers }).pipe(
map((res: Token) => {
let token = res.token;
// store user details and jwt token in local storage to keep user logged in between page refreshes
this.storage.set('accessToken', token);
this.currentTokenSubject.next(token); // <-- also push new token here?
return token;
}));
}
logout() {
// remove user from local storage to log user out
this.storage.remove('accessToken');
this.currentTokenSubject.next(null);
}
}
Now you need to subscribe to the function currentTokenValue()
to retreive the token.现在您需要订阅 function
currentTokenValue()
来检索令牌。
Some component/service一些组件/服务
export class SomeComponent implements OnInit {
token: string;
ngOnInit() {
this.authService.currentTokenValue().subscribe(
token => {
if(token) { // <-- check if token valid because it can also be null
this.token = token;
}
}
);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.