RxJS订阅未接收最终workingHours对象?如何判断数据加载完成
解决方案
要判断workingHours是否为最终加载完成的版本,最可靠的方式是让你的RxJS Store在状态中明确标识数据加载状态,而非依赖数组长度这种间接判断。以下是几种具体实现方式:
1. 给Store添加加载状态字段
在Store的state里新增对应员工的加载状态(比如workingHourLoaded或workingHourLoading),当数据库请求完成、数据全部加载完毕后,将该状态标记为true(或false,根据你的状态定义)。
修改后的订阅代码如下:
// 保存订阅实例,避免内存泄漏 this.subscription = this.context.store.state$ .pipe( map(state => ({ workingHours: state.workingHourList[this.props.employeeId] || [], // 假设store里用workingHourLoaded记录对应员工的数据是否加载完成 isLoaded: state.workingHourLoaded[this.props.employeeId] })), // 只处理加载完成后的状态 filter(({ isLoaded }) => isLoaded) ) .subscribe(({ workingHours }) => { const filteredHours = workingHours.filter( wl => wl.date.getMonth() === this.props.month.getMonth() ); this.updateWorkingHours(filteredHours); }); // 组件卸载时取消订阅 componentWillUnmount() { this.subscription?.unsubscribe(); }
这种方式逻辑清晰,完全依靠明确的状态判断,不会出现误判(比如初始数据长度刚好大于1的情况)。
2. 利用RxJS操作符过滤中间状态(适合一次性加载场景)
如果工时数据是一次性从数据库加载、后续不会再有更新,可以用skipWhile跳过未完成状态,结合take(1)只取第一次完整数据:
this.subscription = this.context.store.state$ .pipe( map(state => state.workingHourList[this.props.employeeId] || []), // 跳过空数组或未加载完成的状态 skipWhile(hours => hours.length === 0), // 只取第一次加载完成的数据,避免重复触发 take(1) ) .subscribe(workingHours => { const filteredHours = workingHours.filter( wl => wl.date.getMonth() === this.props.month.getMonth() ); this.updateWorkingHours(filteredHours); });
注意:如果后续工时数据可能有更新(比如用户修改工时后Store发射新状态),这种方式不适用,因为take(1)会忽略后续更新。
3. 对比数组内容的变化(适合明确数据完整性的场景)
如果能明确判断数组的完整性(比如当月工时记录数量等于当月天数),可以用distinctUntilChanged结合自定义对比,当数组达到完整长度时再处理:
this.subscription = this.context.store.state$ .pipe( map(state => state.workingHourList[this.props.employeeId] || []), // 仅当数组长度等于当月天数时继续 filter(hours => { const monthDays = new Date(this.props.month.getFullYear(), this.props.month.getMonth() + 1, 0).getDate(); return hours.length === monthDays; }), // 避免重复处理相同数组 distinctUntilChanged((prev, curr) => JSON.stringify(prev) === JSON.stringify(curr)) ) .subscribe(workingHours => { const filteredHours = workingHours.filter( wl => wl.date.getMonth() === this.props.month.getMonth() ); this.updateWorkingHours(filteredHours); });
这种方式依赖当月天数判断,适合工时必须每天一条的场景;若允许存在未填工时,会出现误判。
内容的提问来源于stack exchange,提问作者der papa
相关产品推荐
相关产品推荐

