Angular 7中如何合并Userc与Company数据生成Usercco?
解决Firebase返回对象转数组及异步合并数据问题
首先,你的核心问题有两个:
- Firebase的
once('value')返回的data.val()是键值对对象(而非数组),所以usercs.length会失效,无法直接遍历; AddConametoUsercs方法里的getCompany是异步操作,直接返回this.usercco时,异步请求还没完成,结果会是空的。
接下来分步骤解决:
1. 修正getAllUserc:将Firebase对象转为数组
Firebase存储列表数据时,默认会生成唯一键作为key,返回的是{ key1: userc1, key2: userc2 }这样的结构。我们需要把它转成数组,方便后续遍历:
getAllUserc(): Promise<Userc[]> { return new Promise( (resolve, reject) => { firebase.database().ref('userc/').once('value').then( (data: DataSnapshot) => { const usercObj = data.val(); // 将对象转为数组,如果没有数据则返回空数组 const usercArray = usercObj ? Object.values(usercObj) : []; resolve(usercArray); }, (error) => { reject(error); } ); } ); }
如果需要保留Firebase生成的key(比如后续需要更新数据),可以用Object.entries转成包含key的数组:
const usercArray = usercObj ? Object.entries(usercObj).map(([key, value]) => ({ ...value, firebaseKey: key // 把key存到对象里 })) : [];
2. 重构AddConametoUsercs:处理异步请求,合并公司名称
因为每个getCompany都是异步Promise,不能同步循环赋值,需要用Promise.all等待所有请求完成后再返回合并后的数组:
// 先定义方法返回Promise<Usercco[]> async AddConametoUsercs(usercs: Userc[]): Promise<Usercco[]> { // 遍历每个userc,发起公司查询请求,返回包含合并后数据的Promise const userccoPromises = usercs.map(async (userc) => { // 等待公司查询完成 const company = await this.companyService.getCompany(userc.coid); // 合并userc和公司名称,生成Usercco对象 return { ...userc, // 复制userc的所有字段 coname: company?.coname || '未知公司' // 处理公司不存在的情况 } as Usercco; }); // 等待所有Promise完成,返回最终数组 return Promise.all(userccoPromises); }
3. 修正组件的ngOnInit:等待异步操作完成
因为现在AddConametoUsercs返回的是Promise,所以需要用async/await或者.then()处理:
async ngOnInit() { try { // 先等待获取所有userc this.usercs = await this.usercService.getAllUserc(); // 再等待合并公司名称 this.usercco = await this.usercService.AddConametoUsercs(this.usercs); console.log(this.usercco); // 这里就能拿到正确的合并后数据了 } catch (error) { console.error('加载数据失败:', error); } }
或者用.then()链式调用:
ngOnInit() { this.usercService.getAllUserc() .then(usercs => { this.usercs = usercs; return this.usercService.AddConametoUsercs(usercs); }) .then(usercco => { this.usercco = usercco; console.log(this.usercco); }) .catch(error => console.error('加载数据失败:', error)); }
关键说明
- Firebase返回的列表数据默认是对象,必须手动转为数组才能用
length和map/for遍历; - 异步操作不能同步返回结果,必须用
Promise.all或者async/await等待所有请求完成,否则会拿到空的或不完整的usercco; - 加入了
company?.coname的可选链操作,避免公司不存在时出现报错,可以根据实际需求调整默认值。
内容的提问来源于stack exchange,提问作者BenYsil
相关产品推荐
相关产品推荐

