AngularFireAuth-使用无效数据调用的函数DocumentReference.set()。不支持的字段值:未定义

时间:2020-03-08 00:45:24

标签: angular typescript firebase-authentication google-oauth angularfire

我目前正在尝试使用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字段之后出现。

如果您需要任何其他代码来进一步了解我的解决方案,请随时告诉我,并感谢您抽出宝贵的时间来解决我的问题。

0 个答案:

没有答案