Angular Firebase服务多组件调用时escortList未实例化问题
问题分析与解决方案
我来帮你梳理下这个问题的核心原因,以及对应的解决办法:
为什么会出现这个差异?
你在DashboardComponent和StudentOrderedEscortComponent的@Component装饰器里都添加了providers: [EscortService],这会导致每个组件都会创建一个独立的EscortService实例。
- 在
DashboardComponent中,你大概率是在组件初始化(比如ngOnInit)或者模板里调用过escortService.getData()方法,这个方法会给escortList赋值,所以当你调用newEscort()时,escortList已经是有效的引用了。 - 而
StudentOrderedEscortComponent里,你没有调用过getData(),所以它对应的服务实例里的escortList一直是undefined,自然会触发console.log("escortList was null"),甚至后续调用push()时会报错。
另外,你的newEscort()方法依赖外部先调用getData()来初始化内部变量,这本身就是一个不太健壮的设计——服务的方法不应该依赖外部调用顺序才能正常工作。
解决步骤
1. 让服务成为全局单例(核心修复)
首先要解决多实例的问题,把服务的提供者从组件中移除,让整个应用共享同一个服务实例:
- 分别修改两个组件的
@Component配置,删除providers: [EscortService]这一行:
// dashboard.component.ts @Component({ selector: 'dashboard-cmp', moduleId: module.id, templateUrl: 'dashboard.component.html' // 移除providers配置 }) // student-ordered-escort.component.ts @Component({ selector: 'app-student-ordered-escort', templateUrl: './student-ordered-escort.component.html', styleUrls: ['./student-ordered-escort.component.scss'] // 移除providers配置 })
- 推荐使用Angular 6+的
providedIn: 'root'方式注册单例服务,修改EscortService的@Injectable装饰器:
@Injectable({ providedIn: 'root' // 这一行会让服务自动成为全局单例 }) export class EscortService { // ... 原有代码 }
这样就不需要在任何模块的providers里手动注册服务了,Angular会自动处理单例逻辑。
2. 修复newEscort()方法的依赖问题
解决了单例问题后,我们还要让newEscort()不依赖getData()的调用顺序,有两种方式:
方式一:在服务构造函数中初始化escortList
@Injectable({ providedIn: 'root' }) export class EscortService { escortList : AngularFireList<any>; selectedEscort : Escort = new Escort(); constructor(private firebase : AngularFireDatabase) { // 构造函数里直接初始化列表引用 this.escortList = this.firebase.list('something'); } getData(){ return this.escortList; } newEscort(escort : Escort){ if(escort.driver == 'No driver yet' || escort.driver == null) escort.status = "Unassigned"; else escort.status = "Assigned"; // 现在不用再判断escortList是否为null this.escortList.push({ driver : escort.driver, pickup : escort.pickup, dropoff : escort.dropoff, passengers : escort.passengers, no_show : false, status : escort.status, created : Date.now(), finished : null }); } }
方式二:在newEscort()中直接获取列表引用
如果不想在构造函数里初始化,也可以在调用push()时直接获取列表:
newEscort(escort : Escort){ if(escort.driver == 'No driver yet' || escort.driver == null) escort.status = "Unassigned"; else escort.status = "Assigned"; // 直接在这里获取Firebase列表引用,不依赖实例变量 const escortList = this.firebase.list('something'); escortList.push({ driver : escort.driver, pickup : escort.pickup, dropoff : escort.dropoff, passengers : escort.passengers, no_show : false, status : escort.status, created : Date.now(), finished : null }); }
这样不管哪个组件调用newEscort(),都能正常工作,不会出现escortList为undefined的情况了。
内容的提问来源于stack exchange,提问作者beh1
相关产品推荐
相关产品推荐

