cod*_*lex 9 firebase angularfire firebase-authentication angularfire2
我的 Angular 项目成功地使用AngularFireAuth来自@angular/fire的注入连接到本地 Firebase 身份验证模拟器。我使用这些来源作为我的实现参考:
Firebase 文档:检测您的应用以与身份验证模拟器对话
StackOverflow:如何配置 AngularFireAuthModule 和/或 AngularFireAuth 以指向身份验证模拟器
但是,一旦我重新加载页面,登录状态就会丢失,我必须再次登录。
首先,我尝试在 Angular 组件构造函数中像这样设置持久性:
constructor( private _fireauth: AngularFireAuth) {
this._fireAuth.useEmulator(`http://${location.hostname}:9099/`);
this._fireauth.setPersistence(firebase.auth.Auth.Persistence.LOCAL);
}
Run Code Online (Sandbox Code Playgroud)
这没有什么区别。然后我在浏览器网络控制台中注意到,firebase 库在页面加载后确实找到了本地存储的会话,但最初尝试联系谷歌服务器进行验证,这当然失败了,因为它是本地模拟器会话:
这似乎是有道理的,因为_fireAuth.useEmulator()仅在组件构造函数中调用。应用程序的其他部分,例如AngularFireAuthGuard可能会尝试更早地访问身份验证状态方式。useEmulator()在应用程序的任何其他部分可能尝试访问身份验证状态失败之前,尝试调用几次:
Attempt1:调用useEmulator()在@Injectable({providedIn: 'root'})又名服务构造Attempt2:提供一个APP_INITIALIZER在应用程序被引导之前执行代码的方法:export function initializeApp1(afa: AngularFireAuth): any {
return () => {
return new Promise(resolve => {
afa.useEmulator(`http://${location.hostname}:9099/`);
setTimeout(() => resolve(), 5000);
});
};
}
@NgModule({
declarations: [
...
],
imports: [
...,
AngularFireModule.initializeApp(environment.firebase),
AngularFireAuthModule,
...
],
providers: [
AngularFireAuth,
{
provide: APP_INITIALIZER,
useFactory: initializeApp1,
deps: [AngularFireAuth],
multi: true
}
],
bootstrap: [AppComponent]
})
Run Code Online (Sandbox Code Playgroud)
providers: [
{
provide: USE_EMULATOR,
useValue: [location.hostname, 9099]
},
]
Run Code Online (Sandbox Code Playgroud)
我想特别是Attempt3会尽可能早地设置模拟器模式,因为它可以比在构造函数中设置早多少?注射似乎工作,因为浏览器控制台打印在页面加载通常的警告消息:auth.esm.js:133 WARNING: You are using the Auth Emulator, which is intended for local testing only. Do not use with production credentials.。但是,googleapis.com每次在页面加载时检测到本地 indexedDB 中存储的会话时,仍然会触发对 的请求,然后我注销了。还值得注意的是:在Attempt2我使用 5 秒超时显着减慢应用程序初始化速度googleapis.com后,在 Angular 完成初始化之前,页面加载后立即触发请求。
在这一点上,我不知道该尝试什么了。@angular/fire 显然是建立在基本的 Firebase JavaScript 库上的,所以我可能需要更早地设置模拟器模式,但也许我在这里走错了方向?
================================================== ==============
[编辑:]似乎结合Attempt 2与Attempt 3作品,只要该initializeApp1()方法使用一个setTimout()的至少约 100 毫秒。当我删除超时或将其设置为低至 10 毫秒时,登录就会丢失。任何超过 100 毫秒的超时也有效。在这一点上它看起来非常像一个竞争条件?
工作示例:
providers: [
{
provide: USE_EMULATOR,
useValue: [location.hostname, 9099]
},
]
Run Code Online (Sandbox Code Playgroud)
我也注意到这条评论的AngularFireAuth源代码。到目前为止,我真的不明白发生了什么,但也许问题是相关的:
// HACK,当我们导出 auth.Auth 而不是 auth 时,导入 firebase.auth(例如,
import { auth } from 'firebase/app')的开发人员意外地获得了未定义的 auth 对象,因为我们完全懒惰。让我们在这里急切地加载 Auth SDK。仍然可能存在竞争条件……但这大大降低了我们重新评估 API 的可能性。
小智 0
我在代码中调整了初始化应用程序函数,以使用 rxjs 而不是 Promise。
export const initializeApp = (angularFireAuth: AngularFireAuth): (() => Observable<boolean>) => {
if (!environment.firebaseConfig.useEmulator) {
return () => of(true);
} else {
return () => of(true).pipe(
delay(100),
tap(_ => {
angularFireAuth.useEmulator('http://localhost:9099/');
})
);
}
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
782 次 |
| 最近记录: |