使用Firebase防止同一用户对帖子重复点赞的实现方案咨询
Firebase 实现单用户单帖子仅可点赞一次的解决方案
可以实现点赞前的用户身份校验,你当前的代码存在两个核心问题:
- 两次
update操作分开执行,存在并发风险,可能出现点赞数更新成功但用户ID未写入数组,或是反过来的不一致问题 arrayUnion本身是幂等操作(用户ID已存在时不会修改数组),但increment每次调用都会自增1,即使用户已经点过赞,点赞数也会异常累加
优化方案
推荐按「前端前置拦截 + 服务端安全规则兜底」的逻辑实现,彻底避免重复点赞:
- 第一步:前端先查询当前用户是否已点赞,提前拦截重复请求,减少无效服务端调用
const postRef = db.collection("post").doc(postId); const postDoc = await postRef.get(); if (postDoc.exists) { const likedUsers = postDoc.data().usersArray || []; // 已点赞直接返回,不执行后续更新逻辑 if (likedUsers.includes(userId)) { console.log("你已为该帖子点过赞"); return; } // 合并为单次原子更新操作,避免并发不一致 await postRef.update({ likes: firebase.firestore.FieldValue.increment(1), usersArray: firebase.firestore.FieldValue.arrayUnion(userId) }) }
- 第二步:配置Firebase安全规则做服务端强制校验,避免前端被篡改后绕过校验
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /post/{postId} { allow update: if request.auth != null // 点赞场景校验:用户未在原有点赞列表中,新列表包含该用户,且点赞数仅+1 && (!(request.auth.uid in resource.data.usersArray) && request.auth.uid in request.resource.data.usersArray && request.resource.data.likes == resource.data.likes + 1) // 取消点赞场景校验:用户在原有点赞列表中,新列表移除该用户,且点赞数仅-1 || (request.auth.uid in resource.data.usersArray && !(request.auth.uid in request.resource.data.usersArray) && request.resource.data.likes == resource.data.likes - 1) } } }
如果你的业务并发量很高,还可以将前端的先查后改逻辑替换为Firestore事务,彻底解决竞态条件问题。
内容的提问来源于stack exchange,提问作者Minenhle Solson Cele
相关产品推荐
相关产品推荐

