React Native渔船日历功能map处理Firebase异步返回空对象问题
核心问题根源
你现在执行后拿到空schedules的原因非常明确,两个点:
- 给
selectedFishingMethods.map()套await完全起不到等待作用:map遍历返回的是普通数组,不是Promise集合,await根本不会等数组里的异步回调跑完,会直接同步执行后面的打印和状态更新逻辑 - Firebase的
.on('value')是持续事件监听接口,不是可等待的请求Promise:调用后只会注册一个数据变更的回调,不会阻塞当前执行流等数据库返回,你执行状态更新的时候,数据库的回调还没触发,自然拿不到填充好的schedules
可落地的修正方案
调整逻辑
- 如果日历初始化只需要拉一次全量排期数据,把持续监听的
.on('value')换成一次性拉取的once('value'),这个方法会返回标准Promise,可以被await等待 - 用
Promise.all聚合所有选中钓鱼方式对应的拉取任务,等所有任务都拿到数据、完成schedules聚合后,再触发状态更新
修正后的业务代码
const getTourSchedules = async () => { const schedules = {}; // 为每个选中的钓鱼方式创建独立的拉取任务 const fetchTasks = selectedFishingMethods.map(async (item) => { const dbRef = `schedules/${item}`; // 一次性获取指定钓鱼方式下的所有排期数据 const snapShot = await Firebase.database().ref(dbRef).once('value'); if (!snapShot.exists()) return; // 遍历排期条目,按日期聚合 snapShot.forEach((docs) => { const tour = docs.val().contents; const schedule = { endTime: tour.endTime, startTime: tour.startTime, shipName: tour.shipName, } if (!schedules[tour.date]) { schedules[tour.date] = [schedule]; } else { schedules[tour.date].push(schedule); } }) }); // 等待所有钓鱼方式的排期拉取、聚合全部完成 await Promise.all(fetchTasks); // 所有数据处理完再更新状态 setTours({ ...schedules }); };
适配实时场景的说明
如果后续业务需要实时同步渔船预约的状态变化,不需要把.on('value')换成once,但要删掉map循环结束后立刻执行的setTours逻辑,改成在每次监听回调触发、完成schedules聚合后,同步执行setTours,这样数据变化时界面会同步刷新,不会出现空对象的问题。
内容的提问来源于stack exchange,提问作者Taki
相关产品推荐
相关产品推荐

