我目前正在尝试使用AngularFireAuth实施Google登录,但是还无法。当用户登录时,系统会要求他们输入Google凭据-如果不是用户,则将其设置为用户并被接受,否则,将找到他们的凭据并继续登录。我使用的是自定义用户对象,该对象存储了我打算在用户注册以进行未来开发时接受的其他数据。
但是,当我尝试从auth.service.ts中访问代表我的自定义用户的数据对象时,这表示未定义特定字段:
core.js:6014 ERROR Error: Uncaught (in promise): FirebaseError: [code=invalid-argument]: Function DocumentReference.set() called with invalid data. Unsupported field value: undefined (found in field at)
FirebaseError: Function DocumentReference.set() called with invalid data. Unsupported field value: undefined (found in field at)
at new FirestoreError (index.cjs.js:351)
at ParseContext.push../node_modules/@firebase/firestore/dist/index.cjs.js.ParseContext.createError (index.cjs.js:20790)
at UserDataConverter.push../node_modules/@firebase/firestore/dist/index.cjs.js.UserDataConverter.parseScalarValue (index.cjs.js:21149)
at UserDataConverter.push../node_modules/@firebase/firestore/dist/index.cjs.js.UserDataConverter.parseData (index.cjs.js:21015)
at index.cjs.js:21031
at forEach (index.cjs.js:455)
at UserDataConverter.push../node_modules/@firebase/firestore/dist/index.cjs.js.UserDataConverter.parseObject (index.cjs.js:21030)
at UserDataConverter.push../node_modules/@firebase/firestore/dist/index.cjs.js.UserDataConverter.parseData (index.cjs.js:20984)
at UserDataConverter.push../node_modules/@firebase/firestore/dist/index.cjs.js.UserDataConverter.parseMergeData (index.cjs.js:20853)
at DocumentReference.push../node_modules/@firebase/firestore/dist/index.cjs.js.DocumentReference.set (index.cjs.js:21836)
at resolvePromise (zone-evergreen.js:797)
at zone-evergreen.js:707
at fulfilled (tslib.es6.js:70)
at ZoneDelegate.invoke (zone-evergreen.js:359)
at Object.onInvoke (core.js:39699)
at ZoneDelegate.invoke (zone-evergreen.js:358)
at Zone.run (zone-evergreen.js:124)
at zone-evergreen.js:855
at ZoneDelegate.invokeTask (zone-evergreen.js:391)
at Object.onInvokeTask (core.js:39680)
但是,当我查看自定义用户时,对象的“ at”字段具有定义的类型,即“ string”:
export interface User {
uid: string;
at: string;
fName: string;
lName: string;
email: string;
occupation: string;
friendCount: number;
collabCount: number;
aboutMe?: string;
displayName?: string;
photoURL?: string;
}
这是我的auth.service.ts:
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { User } from './user.model';
import { auth } from 'firebase/app';
import { AngularFireAuth } from '@angular/fire/auth';
import { AngularFirestore, AngularFirestoreDocument } from '@angular/fire/firestore';
import { Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class AuthService {
user$: Observable<User>;
constructor(
private afAuth: AngularFireAuth,
private afs: AngularFirestore,
private router: Router
) {
this.user$ = this.afAuth.authState.pipe(
switchMap(user => {
if (user) {
return this.afs.doc<User>(`users/${user.uid}`).valueChanges();
} else {
return of(null);
}
})
);
}
async googleSignin() {
const provider = new auth.GoogleAuthProvider();
const credential = await this.afAuth.auth.signInWithPopup(provider);
return this.updateUserData(credential.user);
}
async signOut() {
await this.afAuth.auth.signOut();
return this.router.navigate(['/']);
}
private updateUserData(user) {
// Sets user data to firestore on login
const userRef: AngularFirestoreDocument<User> = this.afs.doc(`users/${user.uid}`);
const data: User = {
uid: user.uid,
at: user.at,
fName: user.fName,
lName: user.lName,
email: user.email,
occupation: user.occupation,
friendCount: user.friendCount,
collabCount: user.collabCount,
aboutMe: user.aboutMe,
displayName: user.displayName,
photoURL: user.photoURL
};
return userRef.set(data, {merge: true});
}
}
以下是使用auth.service的组件:
(log-in.component.html)
<div *ngIf="auth.user$ | async; then authenticated else guest">
<!-- template will replace this div -->
</div>
<!-- User NOT logged in -->
<ng-template #guest>
<h3>You must be new around here...</h3>
<p>Login to get started.</p>
<button (click)="auth.googleSignin()">
Connect Google
</button>
</ng-template>
<!-- User logged in -->
<ng-template #authenticated>
<div *ngIf="auth.user$ | async as user">
<h3>Howdy, {{ user.displayName }}</h3>
<img [src]="user.photoURL">
<p>UID: {{ user.uid }}</p>
<button (click)="auth.signOut()">Logout</button>
</div>
</ng-template>
(login-component.ts)
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../services/auth.service';
@Component({
selector: 'app-log-in',
templateUrl: './log-in.component.html',
styleUrls: ['./log-in.component.scss']
})
export class LogInComponent implements OnInit {
constructor(public auth: AuthService) { }
ngOnInit() {
}
}
我注意到的另一个重要细节是,当我从自定义用户界面和auth.service中的数据对象中删除“ at”字段时,错误消息将显示未定义字段为“ fName”,即UID后面的字段,类似于“ at”字段。因此,我想知道我是否使用了一些不正确的语法,使得下面的字段在未定义的初始UID字段之后出现。
如果您需要任何其他代码来进一步了解我的解决方案,请随时告诉我,并感谢您抽出宝贵的时间来解决我的问题。