You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firebase v8 updateProfile()更新数据需重登、重复建文档问题

问题描述
  • 尝试将score变量存储到Cloud Firestore对应用户的highscore字段时,数据变更只有重新通过Google账号登录才会显示
  • 即便使用同一个Google账号登录,每次登录都会生成新的用户文档
  • 更新displayName这类Firebase Auth标准字段可以正常生效,但自定义的highscore字段始终无法更新,重新登录、调用reload()方法重载用户数据都无效
  • 使用技术栈:原生Vanilla JS + Firebase Web v8命名空间版本

原问题中实现代码如下:

function gameOver () {
  if (score > highscore) {
    GAME_OVER_TEXT.innerText = 'New Highscore:';
    HIGHSCORE.innerText = `${score} points.`;
    STARS.classList.remove('hide');
    SPARKLE.classList.remove('hide');
    const user = firebase.auth().currentUser;
    user.updateProfile({
      highscore: score
    }).then(() => {
      console.log('Update successful');
    }).catch((error) => {
      console.log('Update unsuccessful' + error);
    });  
    user.currentUser.reload();
  } else {
    GAME_OVER_TEXT.innerText = 'Your score:';
    HIGHSCORE.innerText = `${score} points.`;
  }
}
问题原因

你的代码存在三个核心逻辑错误:

  1. updateProfile()是Firebase Auth的内置方法,仅支持更新Auth系统预设的两个用户属性:displayName和photoURL,传入自定义的highscore字段时,该方法会直接忽略自定义参数,不会做任何存储处理,更不会自动把数据同步到Cloud Firestore。
  2. 代码写法存在语法和时序问题:currentUser是firebase.auth()实例的属性,不是已获取到的user对象的属性,user.currentUser.reload()本身就是无效调用;同时你把reload()写在了updateProfile的异步回调外面,没有等更新操作执行完成就调用重载,就算是合法的内置属性更新也拿不到最新值。
  3. 每次登录创建新文档、数据不同步的本质原因:你没有编写任何向Firestore写入自定义字段的逻辑,且之前存用户数据时没有用用户唯一标识uid作为文档ID,才会导致重复生成文档。
修正方案
  1. 自定义用户业务数据(比如highscore)不要存在Auth用户Profile中,统一存储到Cloud Firestore的用户集合下,固定用用户的uid作为文档ID,从根源上保证同一账号永远对应同一个文档,不会重复创建。
  2. 修正异步逻辑,写入操作完成后再更新本地状态,Firestore存储的业务数据不需要调用reload()方法,直接读写Firestore文档即可。

修正后的可运行代码(适配Firebase v8):

// 提前初始化Firestore实例,确保页面已经引入Firestore相关SDK
const db = firebase.firestore();

function gameOver () {
  if (score > highscore) {
    GAME_OVER_TEXT.innerText = 'New Highscore:';
    HIGHSCORE.innerText = `${score} points.`;
    STARS.classList.remove('hide');
    SPARKLE.classList.remove('hide');
    const user = firebase.auth().currentUser;
    // 未登录状态兜底
    if (!user) {
      console.log('用户未登录,无法保存高分');
      return;
    }
    // 以用户uid为文档ID写入数据,merge:true表示增量更新,不覆盖文档已有字段
    db.collection('users').doc(user.uid).set({
      highscore: score,
      // 可同步存储Auth内置字段,减少后续查询次数
      lastLoginTime: new Date()
    }, { merge: true })
    .then(() => {
      console.log('高分更新成功');
      // 写入成功后再更新本地highscore变量,保证本地和云端数据一致
      highscore = score;
    })
    .catch((error) => {
      console.log('高分更新失败:', error);
    });
  } else {
    GAME_OVER_TEXT.innerText = 'Your score:';
    HIGHSCORE.innerText = `${score} points.`;
  }
}

后续读取逻辑说明

需要获取用户高分时,直接读取对应Firestore文档即可:

// 用户登录成功后拉取用户保存的高分
firebase.auth().onAuthStateChanged(user => {
  if (user) {
    db.collection('users').doc(user.uid).get().then(doc => {
      if (doc.exists) {
        const userData = doc.data();
        highscore = userData.highscore || 0;
      }
    })
  }
})

注意:如果需要给Auth用户配置全局自定义属性(比如用户权限标识),无法通过前端updateProfile方法写入,必须通过Firebase Admin SDK在服务端设置,前端没有直接写入权限。

内容的提问来源于stack exchange,提问作者noKeyboardsLeftToSmash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 11:51:21