首页 > 解决方案 > 无法使用函数更新用户数据

问题描述

在我的 Angular 项目中,我正在尝试使用登录功能让用户使用 google 登录,然后根据他们是否已经拥有该approved角色来更新他们的用户数据。

在尝试完成这项工作时,我的任何console.log陈述都没有触发,所以我不确定我可以做些什么来进入这些块。

async handleSignIn() {
    const credential = await this.afAuth.signInWithPopup(new firebase.default.auth.GoogleAuthProvider());
    return this.manageUserData(credential.user)
}

private async manageUserData(user: User) {
    let data$; // Init Variable
    let update$; // Init Variable
    const userCollection = this.afs.collection<User[]>('users'); // Sets Path for Data
     console.log(user.uid);
    data$ = userCollection.doc<User>(user.uid).snapshotChanges().pipe( // Fetches Document
        map(action => { // Maps To Be Able To Do Things
            const payload = action.payload.data(); // Sets Payload Data as the main `payload` variable
            console.log("In place", payload)
            if(payload.roles.approved == true || false) {
                console.log("main block")
                update$ = {
                    uid: user.uid,
                    email: user.email,
                    displayName: user.displayName,
                    photoURL: user.photoURL
                }
            } else {
                console.log("else block")
                update$ = {
                    uid: user.uid,
                    email: user.email,
                    displayName: user.displayName,
                    photoURL: user.photoURL,
                    roles: {
                        approved: false
                    }
                }
            }
            const userRef: AngularFirestoreDocument<User> = this.afs.doc(`users/${user.uid}`);
            return userRef.set(update$, { merge: true });
        })
    )
}

console.log(user.uid)语句返回我的 Firebase UID:rKlGL943eqfaPVWLh2EEUVBoOvg2

编辑:我也尝试在这里使用三元运算符并更好地组织功能:

function hasApprovedStatus() {
      update$ = {
        uid: user.uid,
        email: user.email,
        displayName: user.displayName,
        photoURL: user.photoURL
      }
      userRef.set(update$, { merge: true });
    }
    function hasNoApprovedStatus() {
      update$ = {
        uid: user.uid,
        email: user.email,
        displayName: user.displayName,
        photoURL: user.photoURL,
        roles: {
          approved: false
        }
      }
      userRef.set(update$, { merge: true })
    }
data$ = userCollection.doc<User>(user.uid).snapshotChanges().pipe( // Fetches Document
      map(action => action.payload.data().roles.approved ? hasApprovedStatus() : hasNoApprovedStatus())
    )
  }

标签: angulartypescriptfirebasegoogle-cloud-firestoreangularfire2

解决方案


问题可能是您的 async 方法manageUserData()实际上并没有做return任何事情。

该方法正在创建一个 ObservableuserCollection.doc<User>(user.uid).snapshotChanges()并将其分配给本地 var data$,但它没有从该方法返回它,也没有订阅它。因此,您似乎正在创建一个永远不会被订阅的 Observable,因此您的map函数将永远不会被调用。

您需要做的是return您正在创建的 Observable(另外,除非您打算将该 var 用于某事,否则无需将其分配给本地 var):

return userCollection.doc<User>(user.uid).snapshotChanges().pipe(...

这将导致manageUserData()返回一个async解析为 Observable 的 Promise(因为它是 )。

由于handleSignIn()返回 的返回值manageUserData(),因此该 Promise 将传递给调用 的任何人handleSignIn()。该调用方法看起来像这样:

async signIn() {
  const handle: Observable<any> = await this.handleSignIn();

  handle.subscribe();
}

由于handleSignIn()返回一个 Promise,我们必须await通过该 Promise 的解析然后订阅生成的 Observable(即您的snapshotChanges())。

除非您需要它是基于 Promise 的,否则您可能会考虑简单地返回 Observable ,manageUserData()handleSignIn()不是将其包装在 Promise 中(通过制作这些方法async),那么您不需要额外的步骤await来解决 Promise。

这是一个 StackBlitz,其中该方法调用链的模拟版本正常工作。

更新响应评论,2020 年 12 月 29 日:

如果您需要过滤流以便map函数中的第一行const payload = action.payload.data()始终从方法调用中检索值,您可以在管道action.payload.data()中添加过滤器map运算符:

return userCollection.doc<User>(user.uid).snapshotChanges().pipe(
  filter(action => Boolean(action.payload?.data?.())),
  map(action => { ... )
)

其他一些观察:

  1. map函数的第一行是
const payload = action.payload.data();

您在其中调用属性的data()方法payload。真的data()是一种方法还是只是一种属性?

  1. map函数中的第三行是
if(payload.roles.approved == true || false) { ...

这是一个奇怪的构造条件。您正在测试什么条件?

本质上什么都不做, || false因为它只评估 if payload.roles.approved == trueis false,所以你只是在检查if (false || false),这似乎不是很有用。

如果您的意图是检查 if payload.roles.approvedis either strict 或strict ,那么您会这样做(请注意,我使用的是严格相等true,而不是松散相等,因为这是首选,除非有充分的理由使用松散相等):false===

if(payload.roles.approved === true || payload.roles.approved === false) { ...

推荐阅读