Ionic2中AngularFire2 Observable.complete回调不触发,如何解决?
我明白你遇到的困扰了——在使用AngularFire2的list订阅时,complete回调始终没反应,哪怕手动取消订阅也看不到"done!"输出。这其实是AngularFire结合Firebase实时数据库的设计特性导致的,咱们一步步来解决:
为什么complete回调不触发?
AngularFireDatabase的list()返回的是一个持续监听的Observable,它的核心作用是实时同步Firebase数据库里/myTest节点的变化——只要节点有新增、修改、删除操作,这个Observable就会推送新数据。这类Observable不会主动发出complete信号,因为它的使命是一直监听数据变化;而unsubscribe()只是让你停止接收推送,并不会触发Observable的complete回调(这是RxJS的设计规则:complete是Observable主动结束的通知,unsubscribe是订阅者主动取消,两者是独立操作)。
解决方案
根据你的实际需求,有两种处理方式:
1. 只需要获取一次数据,不需要实时更新
如果你仅需加载一次数据,之后不需要同步更新,那可以用RxJS的take(1)操作符,让Observable只推送一次数据就自动完成:
// 先导入take操作符 import 'rxjs/add/operator/take'; constructor(public af: AngularFireDatabase, ...) { this.temp = af.list('/myTest').valueChanges().take(1).subscribe(data => { // 处理你的数据 }, error => { console.log(error); }, () => { console.log("done!"); // 现在会正常触发了 }); }
take(1)会告诉Observable:只取第一次推送的数据,随后就发出complete信号,这样你的第三个回调就能执行了。
2. 需要实时监听,但要在特定时机执行"完成"逻辑
如果你需要持续监听数据变化,但想在某个时机(比如页面销毁)执行类似complete的逻辑,那可以在手动取消订阅前,直接调用你的目标代码。比如在页面的ngOnDestroy钩子中处理:
import { OnDestroy } from '@angular/core'; import { Subscription } from 'rxjs/Subscription'; export class YourPage implements OnDestroy { temp: Subscription; constructor(public af: AngularFireDatabase, ...) { this.temp = af.list('/myTest').subscribe(data => { // 处理实时更新的数据 }, error => { console.log(error); }); } ngOnDestroy() { console.log("done!"); // 在取消订阅前执行你的完成逻辑 this.temp.unsubscribe(); } }
这样在页面销毁时,就能执行你原本放在complete回调里的代码了。
补充说明
你之前调用this.temp.closed返回的是订阅是否被取消的状态,它和Observable是否发出complete信号没有关联——哪怕closed是true,也不会触发complete回调,因为这个回调只有Observable主动发出complete通知才会执行。
内容的提问来源于stack exchange,提问作者Harine

