在用户注销时初始化所有全局服务的更好方法



我需要在用户注销时清除所有数据或初始化所有全局服务。所以我用了window.location.reload();,它完成了任务。但我是否有更好的方法,因为我目前的hack给用户带来了糟糕的UI/UX ?

private refreshTheApp(): void {

window.location.reload();

}

问题是这种全局单例服务:

@Injectable({
providedIn: 'root'
})
export class EventDataService {}

最简单的方法

最简单的方法是使用类似AppEventsService的东西,其中有几个主题导出为可观察对象,以便任何组件/服务都可以订阅它的更改。

import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class AppEventsService {
public userSignOut$: Observable<void>;
private userSignOut$$ = new Subject<void>();
constructor() {
this.userSignOut$ = this.userSignOut$$.asObservable();
}
public emitUserSignOutEvent(): void {
this.userSignOut$$.next();
}
}

这样,当用户退出时,您可以调用this.appEventsService. emitUserSignOutEvent(),任何其他服务/组件都可以订阅此事件,如this.appEventsService.userSignOut$.subscribe(() => {...})

更详细的方法

一个更好的方法可能是有一个类似于应用程序事件系统的东西,其中每个事件都有一个类型和一个类型为有效载荷。请看看这个Github的repo。

重要:这只是一个演示,肯定有很多改进的空间!!

本演示的基本元素是事件、自定义过滤器操作符和AppEventsService

<<p>

1)事件/strong>定义事件有点冗长,但好处是事件的有效负载将被键入。

例如,以下代码定义了UserSignInEvent:
import { BaseEvent } from './base.event';
export const USER_SIGN_IN = 'USER_SIGN_IN';
// Event definition
export interface UserSignInEvent {
type: typeof USER_SIGN_IN;
payload: {
id: number;
email: string;
};
}
// Event creator function
export const userSignInEvent = (
id: number,
email: string
): UserSignInEvent => ({
type: USER_SIGN_IN,
payload: { id, email },
});
// Event filtering function
export const isUserSignInEvent = (event: BaseEvent): event is UserSignInEvent =>
event.type === USER_SIGN_IN;
上面的代码不仅定义了事件,还定义了一个允许我们创建事件实例的函数,以及另一个允许我们根据其type识别事件的函数。它们将在以后调度和订阅事件时使用。

2)过滤器操作符

该操作符允许我们(显然)根据其类型过滤事件,以便每个订阅者可以侦听特定的事件。但是操作符也使它的有效载荷类型为:

import { OperatorFunction } from 'rxjs';
import { filter, map } from 'rxjs/operators';
export const filterEvent =
<T, R extends T>(guard: (value: T) => value is R): OperatorFunction<T, R> =>
(source) =>
source.pipe(
map((value) => {
if (guard(value)) {
return value;
}
return null;
}),
filter((value) => !!value)
);

3)服务

这是一个非常简单的服务,公开了一个方法来分派事件,另一个方法来订阅特定的事件:

import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { BaseEvent } from '../events/base.event';
@Injectable({ providedIn: 'root' })
export class AppEventsService {
private eventsDispatcher = new Subject<BaseEvent>();
public dispatch(event: BaseEvent): void {
this.eventsDispatcher.next(event);
}
public get onEvents$(): Observable<BaseEvent> {
return this.eventsDispatcher.asObservable();
}
}

使用事件

调度事件非常简单,这要归功于帮助我们创建事件实例的函数:

import { Component } from '@angular/core';
import { userSignInEvent, userSignOutEvent } from 'src/app/events';
import { AppEventsService } from 'src/app/services/app-events.service';
@Component({
selector: 'app-tab2',
templateUrl: 'tab2.page.html',
styleUrls: ['tab2.page.scss'],
})
export class Tab2Page {
constructor(private appEventsService: AppEventsService) {}
public dispatchSignInEvent(): void {
const id = Math.floor(Math.random() * 10);
const email = `test+${id}@user.com`;
console.log(`===> TAB 2: about to dispatch UserSingInEvent: ${id} - ${email}`);
this.appEventsService.dispatch(userSignInEvent(id, email));
}
public dispatchSignOutEvent(): void {
console.log(`===> TAB 2: about to dispatch UserSingOutEvent`);
this.appEventsService.dispatch(userSignOutEvent());
}
}

代码的最后一部分是订阅这些事件。

import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { isUserSignInEvent, isUserSignOutEvent } from 'src/app/events';
import { filterEvent } from 'src/app/operators';
import { AppEventsService } from 'src/app/services/app-events.service';
@Component({
selector: 'app-tab1',
templateUrl: 'tab1.page.html',
styleUrls: ['tab1.page.scss'],
})
export class Tab1Page implements OnInit, OnDestroy {
public id: number;
public email: string;
public isSignedIn: boolean;
private unsubscribe$ = new Subject<void>();
constructor(private appEventsService: AppEventsService) {}
ngOnInit() {
this.appEventsService.onEvents$
.pipe(filterEvent(isUserSignInEvent), takeUntil(this.unsubscribe$))
.subscribe(({ payload }) => {
const { id, email } = payload;
console.log(`===> TAB 1: received UserSingInEvent: ${id} - ${email}`);
this.id = id;
this.email = email;
this.isSignedIn = true;
});
this.appEventsService.onEvents$
.pipe(filterEvent(isUserSignOutEvent), takeUntil(this.unsubscribe$))
.subscribe(() => {
console.log(`===> TAB 1: received UserSingOutEvent`);
this.id = null;
this.email = null;
this.isSignedIn = false;
});
}
ngOnDestroy() {
this.unsubscribe$.next();
this.unsubscribe$.unsubscribe();
}
}

代码最重要的部分是这个:

this.appEventsService.onEvents$
.pipe(filterEvent(isUserSignInEvent)) // <----
.subscribe(({ payload }) => {
// the payload is typed here!
});

多亏了filterEvent操作符和isUserSignInEvent函数,事件的有效载荷被键入:)

相关内容

最新更新