如何在刷新页面时获取到 运行 的服务?
How to get a Service to to run upon refreshing the page?
我正在通过 angular/angularfire 库使用 Angular 和 Firebase。我有两个服务:管理用户身份验证的 HandleAuthService 和管理实时数据库的 CrowboxdbService。目前,在我的主页组件中,我正在检查用户是否已登录。如果他们已登录,他们可以访问其他站点页面。如果他们没有登录,我会为他们提供一个按钮来注册或登录。这样做后,他们将被重定向到另一个页面,在那里他们可以查看他们的数据(在 data.component.ts).
当用户首次注册或首次登录时,我没有遇到任何问题。我的所有组件都可以从 HandleAuthService 访问 authState,因此可以访问诸如用户名和uid。我使用 uid 更新 RTDB 中的用户数据。
我遇到的问题是在页面刷新时出现的。当页面刷新时,似乎 HandleAuthService 运行s 比其他一切都晚了一点。所以组件无法检索相关信息,例如 uid.
以下是每个文件的代码片段:
app.module.ts:
在这里,我将 HandleAuthService 设置为提供者:
//imported the service (as well as in the angular import)
import { HandleAuthService } from './services/shared/handle-auth.service';
//set it as a provider for the other components
providers: [HandleAuthService]
HandleAuthService
constructor(private fireAuth: AngularFireAuth, private ngZone: NgZone, private router: Router) {
/* initialise the currentUserId by retrieving it from the authState */
this.fireAuth.authState.subscribe(user => {
if (user) {
console.log("User is LOGGED IN");
this.currentUserState = {
uid: user.uid!,
email: user.email!,
displayName: user.displayName!
};
console.log("Current User State is:");
console.log(this.currentUserState);
//set the object in the localstorage
localStorage.setItem('user', JSON.stringify(this.currentUserState));
} else {
console.log("User is not logged in?");
localStorage.setItem('user', "null");
}
})
}
login() {
/* Sign in or Sign Up with google's pop up.*/
return this.googleLogin( new firebase.auth.GoogleAuthProvider());
}
googleLogin(provider:any) {
return this.fireAuth.signInWithPopup(provider)
.then((result)=> {
this.ngZone.run(() => {
this.router.navigate(['data']);
});
this.setUser(result.user);
})
.catch((error) => {
console.log(error);
})
}
setUser(result:any) {
this.currentUserState = {
uid : result.uid,
email : result.email,
displayName : result.displayName
};
}
现在,在 data.component.ts 中,我调用 HandleAuthService 并使用它,只要它有效由于页面尚未刷新。
constructor(private authService: HandleAuthService, private crowboxService: CrowboxdbService) {}
ngOnInit(): void {
//upon the view rendering, get the User Id
this.currentUserId = this.authService.currentUserState?.uid;
console.log("Current User Id is " );
console.log(this.currentUserId);
this.checkIfUserExists();
}
在ngOnInit()
中,我尝试打印出用户ID。如果页面已刷新,则 returns undefined
。但是,如果用户在登录后(或从主页)直接导航到该页面,它就可以工作。这是为什么?我怎样才能确保 HandleAuthService 总是第一个成为 运行?
CrowboxdbService 也面临同样的问题
在此服务中,对于来自 RTDB 的 push/update/read 值,我需要用户 ID。当用户首次登录时,我可以从 HandleAuthService 中获取用户 ID。但是,刷新页面后,此服务无法从 HandleAuthService 获取 ID,而是求助于从本地存储获取 ID。但是,我不想这样做,因为它对已在 firebase 中设置的受限身份验证规则没有帮助。
constructor(private db: AngularFireDatabase, private handleAuth: HandleAuthService) {
//try to get the user id from handleAuth (if this is the first time loggin in)
this.currentUserId = this.handleAuth.currentUserState?.uid;
}
//if you cannot get the user id from handleAuth, then get it from the localStorage
if(!this.currentUserId) {
console.log("Error in crowboxdb Service - Cannot retrieve user id from handleAuth");
//get the user information from the local storage
const item = localStorage.getItem('user');
if (item !=='undefined' && item!==null) {
const currentUser = JSON.parse(item);
this.currentUserId = currentUser.uid!;
}
}
是的,这是异步的,所以刷新后需要一段时间才能设置用户。这就是它的工作原理并尝试接受它:)
我通常做的是将值赋给一个 observable,在我看来也不需要 localStorage,firebase 总是会发出给你,这就是它的美妙之处。如果存在,您总是从 authstate 获取用户。所以我会如前所述分配给一个可观察对象并在组件中订阅它。如果你附上take(1)
,你不需要退订,它只会发出一次。所以服务:
currentUser$ = this.fireAuth.authState.pipe(
map(user => {
if (user) {
return { uid: user.uid, email: user.email, displayName: user.displayName }
}
return null;
})
);
现在无论你在哪里需要此用户信息,只需订阅即可:
ngOnInit(): void {
this.authService.currentUser$.subscribe(user => console.log(user))
}
更好的是,如果您在模板中使用此用户信息,而不是使用 subscribe
,请使用 async
管道。另外我建议你输入你的数据,angularfire 有自己的类型,但你也可以编写自己的接口。值得,以后对你有帮助! :)
我正在通过 angular/angularfire 库使用 Angular 和 Firebase。我有两个服务:管理用户身份验证的 HandleAuthService 和管理实时数据库的 CrowboxdbService。目前,在我的主页组件中,我正在检查用户是否已登录。如果他们已登录,他们可以访问其他站点页面。如果他们没有登录,我会为他们提供一个按钮来注册或登录。这样做后,他们将被重定向到另一个页面,在那里他们可以查看他们的数据(在 data.component.ts).
当用户首次注册或首次登录时,我没有遇到任何问题。我的所有组件都可以从 HandleAuthService 访问 authState,因此可以访问诸如用户名和uid。我使用 uid 更新 RTDB 中的用户数据。
我遇到的问题是在页面刷新时出现的。当页面刷新时,似乎 HandleAuthService 运行s 比其他一切都晚了一点。所以组件无法检索相关信息,例如 uid.
以下是每个文件的代码片段:
app.module.ts: 在这里,我将 HandleAuthService 设置为提供者:
//imported the service (as well as in the angular import)
import { HandleAuthService } from './services/shared/handle-auth.service';
//set it as a provider for the other components
providers: [HandleAuthService]
HandleAuthService
constructor(private fireAuth: AngularFireAuth, private ngZone: NgZone, private router: Router) {
/* initialise the currentUserId by retrieving it from the authState */
this.fireAuth.authState.subscribe(user => {
if (user) {
console.log("User is LOGGED IN");
this.currentUserState = {
uid: user.uid!,
email: user.email!,
displayName: user.displayName!
};
console.log("Current User State is:");
console.log(this.currentUserState);
//set the object in the localstorage
localStorage.setItem('user', JSON.stringify(this.currentUserState));
} else {
console.log("User is not logged in?");
localStorage.setItem('user', "null");
}
})
}
login() {
/* Sign in or Sign Up with google's pop up.*/
return this.googleLogin( new firebase.auth.GoogleAuthProvider());
}
googleLogin(provider:any) {
return this.fireAuth.signInWithPopup(provider)
.then((result)=> {
this.ngZone.run(() => {
this.router.navigate(['data']);
});
this.setUser(result.user);
})
.catch((error) => {
console.log(error);
})
}
setUser(result:any) {
this.currentUserState = {
uid : result.uid,
email : result.email,
displayName : result.displayName
};
}
现在,在 data.component.ts 中,我调用 HandleAuthService 并使用它,只要它有效由于页面尚未刷新。
constructor(private authService: HandleAuthService, private crowboxService: CrowboxdbService) {}
ngOnInit(): void {
//upon the view rendering, get the User Id
this.currentUserId = this.authService.currentUserState?.uid;
console.log("Current User Id is " );
console.log(this.currentUserId);
this.checkIfUserExists();
}
在ngOnInit()
中,我尝试打印出用户ID。如果页面已刷新,则 returns undefined
。但是,如果用户在登录后(或从主页)直接导航到该页面,它就可以工作。这是为什么?我怎样才能确保 HandleAuthService 总是第一个成为 运行?
CrowboxdbService 也面临同样的问题 在此服务中,对于来自 RTDB 的 push/update/read 值,我需要用户 ID。当用户首次登录时,我可以从 HandleAuthService 中获取用户 ID。但是,刷新页面后,此服务无法从 HandleAuthService 获取 ID,而是求助于从本地存储获取 ID。但是,我不想这样做,因为它对已在 firebase 中设置的受限身份验证规则没有帮助。
constructor(private db: AngularFireDatabase, private handleAuth: HandleAuthService) {
//try to get the user id from handleAuth (if this is the first time loggin in)
this.currentUserId = this.handleAuth.currentUserState?.uid;
}
//if you cannot get the user id from handleAuth, then get it from the localStorage
if(!this.currentUserId) {
console.log("Error in crowboxdb Service - Cannot retrieve user id from handleAuth");
//get the user information from the local storage
const item = localStorage.getItem('user');
if (item !=='undefined' && item!==null) {
const currentUser = JSON.parse(item);
this.currentUserId = currentUser.uid!;
}
}
是的,这是异步的,所以刷新后需要一段时间才能设置用户。这就是它的工作原理并尝试接受它:)
我通常做的是将值赋给一个 observable,在我看来也不需要 localStorage,firebase 总是会发出给你,这就是它的美妙之处。如果存在,您总是从 authstate 获取用户。所以我会如前所述分配给一个可观察对象并在组件中订阅它。如果你附上take(1)
,你不需要退订,它只会发出一次。所以服务:
currentUser$ = this.fireAuth.authState.pipe(
map(user => {
if (user) {
return { uid: user.uid, email: user.email, displayName: user.displayName }
}
return null;
})
);
现在无论你在哪里需要此用户信息,只需订阅即可:
ngOnInit(): void {
this.authService.currentUser$.subscribe(user => console.log(user))
}
更好的是,如果您在模板中使用此用户信息,而不是使用 subscribe
,请使用 async
管道。另外我建议你输入你的数据,angularfire 有自己的类型,但你也可以编写自己的接口。值得,以后对你有帮助! :)