AngularFire2实现用户校验后新增/更新Firebase实时数据库用户问题
解决AngularFire2中新增用户时重复触发更新的问题
我完全理解你碰到的麻烦——你当前的代码里用valueChanges()持续监听数据库中对应邮箱的用户数据,这就导致当你新增用户后,数据库的更新会再次触发这个订阅,进而错误地执行updateVisitor方法,形成不必要的重复操作。
问题根源
valueChanges()返回的是一个持续的Observable,它会在数据库对应节点的数据发生任何变化时都发出新值。所以当你调用addVisitor新增用户后,数据库里的visitors节点更新,这个订阅就会再次触发,此时list.length不再为0,就会执行updateVisitor,这显然不是你想要的逻辑。
解决方案:只获取一次数据
我们需要让Observable只返回一次数据,然后自动取消订阅,这样后续的数据库更新就不会触发这段逻辑了。可以使用RxJS的take(1)操作符来实现这个需求。
步骤1:导入take操作符
在你的组件文件顶部,添加RxJS操作符的导入:
import { take } from 'rxjs/operators';
步骤2:修改onSubmit方法
在订阅valueChanges()时,通过pipe(take(1))来限制只取一次数据:
onSubmit(form: NgForm) { const formValue = form.value; this._visitorService.getIndividualVisitor(formValue.email) .valueChanges() .pipe(take(1)) // 仅获取一次数据后立即取消订阅 .subscribe(list => { console.log(list); if (list.length === 0) { console.log('email doesn\'t exist, creating new user'); this._visitorService.addVisitor(formValue); } else { console.log('email exists'); this._visitorService.updateVisitor(formValue); } }); }
步骤3:保持getIndividualVisitor方法不变
你的查询方法是正确的,不需要修改:
getIndividualVisitor(email:string){ this.list = this.firebase.list('visitors', ref => ref.orderByChild('email').equalTo(email)); return this.list; }
为什么这个方案有效?
take(1)操作符会告诉Observable:只发出第一个到达的值,然后立即完成并取消订阅。这样当你新增用户导致数据库更新时,之前的订阅已经结束了,不会再次触发逻辑判断,也就避免了新增后又执行更新的问题。
额外注意事项
- 确保你已经安装了和angularfire2 5.0.0-rc.4兼容的RxJS版本(通常RxJS 5.x即可)
- 这种方式也能避免潜在的内存泄漏,因为订阅会自动取消,不需要手动调用
unsubscribe()
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

