AngularFire .set()在Twitter登录后无限等待无响应,求解决方法
问题:Twitter登录后Firestore写入卡住无法进入then/catch
我正在使用Angular结合AngularFire开发首个应用,通过Twitter登录后,尝试在Firestore的users集合中添加用户文档。processLoggedUser函数中的Firestore写入代码永远无法进入.then()或.catch(),一直处于等待状态,但将这段代码放在构造函数或其他位置时,却能正常在Firestore中创建文档。
完整的processLoggedUser函数
processLoggedUser(): Promise<number> { return this.afAuth.getRedirectResult().then(async result => { if (result.user) { const uid = result.user.uid; const credential = result.credential as firebase.default.auth.OAuthCredential; console.log('Twitter answer of AuthLogin: ', result) this.uid = uid let code = 0 // 0 = default code -> error if (result.additionalUserInfo.isNewUser) { console.log("New user") this.user = { uid: this.uid, email: result.user.email, displayName: result.user.displayName, photoURL: result.user.photoURL.replace('_normal', ''), miniPhotoURL: result.user.photoURL, accessToken: credential.accessToken, secret: credential.secret, twitterId: result.additionalUserInfo.profile["id"], username: result.additionalUserInfo.username, bio: result.additionalUserInfo.profile["description"], verified: result.additionalUserInfo.profile["verified"], wallet: 0, staff: false, banned: false, hidden: false }; console.log(this.user) await this.afs.collection('users').doc(this.uid).set(this.user || {nome: "oops"}).then(res => { console.log("User created", res) code = 2 // Number code for new user }).catch(err => { console.log("Error creating user", err) code = 0 // Number code for error }) return 2 } else { await this.getUser(uid).then(res => res.subscribe(res => { if (res == undefined) { this.signOut() code = 4 // Number code for user not found } else { this.user = res console.log("Existing user", this.user) code = 1 // Number code for existing user } })) } return code }else { return 3 } }).catch((error) => { console.warn(error) return 0 // Number code for error }) }
困扰的代码片段
await this.afs.collection('users').doc(this.uid).set(this.user).then(res => { console.log("User created", res) code = 2 // Number code for new user }).catch(err => { console.log("Error creating user", err) code = 0 // Number code for error })
问题分析与解决方法
核心问题
- 混合使用async/await与.then()/.catch():await本身会等待Promise完成,但链式调用
.then()/.catch()会导致Promise嵌套,破坏await的等待逻辑,进而出现卡住的情况。 - 提前返回结果:新用户分支中,在await之后直接
return 2,完全忽略Firestore操作的实际结果,内部修改code变量的逻辑根本不会影响返回值。 - Observable未转Promise:现有用户分支中,
getUser返回的是Observable,await对Observable无效,导致代码不会等待数据获取完成就返回初始值code=0。
修正后的代码实现
1. 新用户分支修正(统一用async/await + try/catch)
if (result.additionalUserInfo.isNewUser) { console.log("New user") this.user = { uid: this.uid, email: result.user.email, displayName: result.user.displayName, photoURL: result.user.photoURL.replace('_normal', ''), miniPhotoURL: result.user.photoURL, accessToken: credential.accessToken, secret: credential.secret, twitterId: result.additionalUserInfo.profile["id"], username: result.additionalUserInfo.username, bio: result.additionalUserInfo.profile["description"], verified: result.additionalUserInfo.profile["verified"], wallet: 0, staff: false, banned: false, hidden: false }; console.log(this.user); try { // 直接await Firestore的set操作,无需链式调用then/catch await this.afs.collection('users').doc(this.uid).set(this.user); console.log("User created"); return 2; // 新用户创建成功 } catch (err) { console.log("Error creating user", err); return 0; // 创建失败 } }
2. 现有用户分支修正(Observable转Promise)
首先需要导入firstValueFrom(RxJS 7+版本):
import { firstValueFrom } from 'rxjs';
然后修改分支代码:
else { try { // 将Observable转换为Promise,用await等待结果 const userData = await firstValueFrom(this.getUser(uid)); if (!userData) { this.signOut(); return 4; // 用户未找到 } else { this.user = userData; console.log("Existing user", this.user); return 1; // 已有用户 } } catch (err) { console.log("Error fetching user", err); return 0; // 获取用户失败 } }
3. 整体函数优化(统一async/await语法)
把最外层的.then()也改成async/await,进一步简化逻辑:
async processLoggedUser(): Promise<number> { try { const result = await this.afAuth.getRedirectResult(); if (result.user) { const uid = result.user.uid; const credential = result.credential as firebase.default.auth.OAuthCredential; console.log('Twitter answer of AuthLogin: ', result); this.uid = uid; if (result.additionalUserInfo.isNewUser) { this.user = { /* 保持原用户数据结构 */ }; try { await this.afs.collection('users').doc(this.uid).set(this.user); console.log("User created"); return 2; } catch (err) { console.log("Error creating user", err); return 0; } } else { try { const userData = await firstValueFrom(this.getUser(uid)); if (!userData) { this.signOut(); return 4; } else { this.user = userData; console.log("Existing user", this.user); return 1; } } catch (err) { console.log("Error fetching user", err); return 0; } } } else { return 3; // 无登录结果 } } catch (error) { console.warn(error); return 0; // 登录过程出错 } }
内容的提问来源于stack exchange,提问作者Felix
相关产品推荐
相关产品推荐

