Angular+AngularFire2操作Firestore:subscribe外部无法访问数据求助
解决AngularFire2获取Firestore文档数据仅在订阅内可用的问题
这是个典型的异步操作时序问题,我来帮你理清楚根源和解决办法~
问题根源
Observable是异步数据流,subscribe里的回调函数只会在Firestore返回数据后才执行。而你代码里外部的console.log是在订阅刚创建时就同步执行了,这时候this.dataD还只是subscribe方法返回的订阅对象(也就是你看到的Subscriber实例),根本没等到Firestore的数据返回,自然拿不到文档内容。
另外你代码里还有个小问题:你先把订阅对象赋值给了this.dataD,之后又在回调里把数据覆盖给它,虽然回调里能拿到数据,但这种写法很容易混淆。
推荐解决方案:用Angular的async管道(最省心)
async管道是Angular专门为异步数据流设计的,它会自动帮你完成订阅、取消订阅,还能避免内存泄漏,代码也更简洁。
- 组件代码修改:
ngOnInit() { this.id = this.route.snapshot.params['id']; // 直接把Observable赋值给变量,不要手动订阅 this.data$ = this.dataService.getDataDetails(this.id); }
- 模板中使用
async管道:
<!-- 用async管道订阅Observable,并用as语法把数据赋值给局部变量 --> <div *ngIf="data$ | async as data"> <p>地址:{{ data.adresse }}</p> <p>办公室:{{ data.bureau }}</p> <p>中心:{{ data.centre }}</p> <!-- 其他字段按需展示 --> </div>
备选方案:手动订阅并管理生命周期
如果你一定要手动处理订阅,记得要在组件销毁时取消订阅,同时所有依赖数据的操作都要放在subscribe回调内部:
- 组件代码修改:
import { Subscription } from 'rxjs'; // 定义一个订阅变量,用于后续取消订阅 private dataSubscription!: Subscription; ngOnInit() { this.id = this.route.snapshot.params['id']; this.dataSubscription = this.dataService.getDataDetails(this.id) .subscribe(res => { this.dataD = res; console.log('拿到数据了:', this.dataD); // 所有需要用数据的同步操作都要写在这里 }); // 这里的console.log永远拿不到数据,别在这里用! } // 组件销毁时取消订阅,防止内存泄漏 ngOnDestroy() { if (this.dataSubscription) { this.dataSubscription.unsubscribe(); } }
内容的提问来源于stack exchange,提问作者RxDev
相关产品推荐
相关产品推荐

