使用Angularfire2+Firebase分批取数据时组件报Property 'do'错误求解
解决Angularfire2分批获取数据时的
Property 'do' does not exist on type 'void'错误 看起来你遇到的问题主要来自两个方面:RxJS版本的操作符命名变化,以及数据获取方法的返回值类型错误,我来一步步帮你解决:
1. 错误根源解析
- 首先,RxJS 6+ 已经把原有的
do操作符改名为tap了,如果你还在使用do,TypeScript会报错找不到这个方法。 - 其次,如果你的服务方法里直接调用了
.subscribe()而不是返回Observable,那么方法的返回值就是void,自然无法链式调用任何RxJS操作符(包括do/tap)。
2. 正确实现分批+滚动加载的步骤
第一步:调整服务层的Firebase数据获取逻辑
确保服务方法返回Observable,使用tap替代do,并记录分页用的最后一个文档:
import { Injectable } from '@angular/core'; import { AngularFirestore } from '@angular/fire/firestore'; import { Observable, of } from 'rxjs'; import { tap } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class YourDataService { private lastVisibleDoc: any; // 存储分页的最后一个文档 private pageSize = 10; // 每页加载的数据量 constructor(private afs: AngularFirestore) {} // 获取初始数据 getInitialData(): Observable<any[]> { return this.afs.collection('your-collection-name', ref => ref.orderBy('createdAt', 'desc').limit(this.pageSize) // 按创建时间倒序,取前10条 ).snapshotChanges().pipe( tap(actions => { // 更新最后一个可见文档,用于下一页加载 if (actions.length > 0) { this.lastVisibleDoc = actions[actions.length - 1].payload.doc; } }) ); } // 加载更多数据 loadMoreData(): Observable<any[]> { // 如果没有最后一个文档,返回空数组避免报错 if (!this.lastVisibleDoc) return of([]); return this.afs.collection('your-collection-name', ref => ref.orderBy('createdAt', 'desc') .startAfter(this.lastVisibleDoc) .limit(this.pageSize) ).snapshotChanges().pipe( tap(actions => { // 只有当有新数据时,才更新最后一个文档 if (actions.length > 0) { this.lastVisibleDoc = actions[actions.length - 1].payload.doc; } }) ); } }
第二步:组件中处理滚动事件与数据合并
在组件里监听滚动事件,触发加载更多,并合并初始数据和后续加载的数据:
import { Component, OnInit, HostListener, OnDestroy } from '@angular/core'; import { YourDataService } from './your-data.service'; import { Observable, merge } from 'rxjs'; import { scan, switchMap, tap } from 'rxjs/operators'; @Component({ selector: 'app-data-list', template: ` <div class="data-item" *ngFor="let item of dataList$ | async"> <!-- 替换成你的模板内容 --> <h3>{{ item.payload.doc.data().title }}</h3> <p>{{ item.payload.doc.data().content }}</p> </div> <div class="loading" *ngIf="isLoading">加载中...</div> ` }) export class DataListComponent implements OnInit, OnDestroy { dataList$: Observable<any[]>; isLoading = false; private scrollEventHandler: () => void; constructor(private dataService: YourDataService) {} ngOnInit() { // 初始数据数据流 const initialData$ = this.dataService.getInitialData(); // 滚动触发的加载更多数据流 const scrollLoad$ = new Observable(observer => { this.scrollEventHandler = () => { // 检测是否滚动到页面底部附近(100px阈值) const isNearBottom = (window.innerHeight + window.scrollY) >= document.body.offsetHeight - 100; if (isNearBottom && !this.isLoading) { this.isLoading = true; observer.next(); } }; window.addEventListener('scroll', this.scrollEventHandler); return () => window.removeEventListener('scroll', this.scrollEventHandler); }).pipe( switchMap(() => this.dataService.loadMoreData()), tap(() => this.isLoading = false) // 加载完成后重置加载状态 ); // 合并初始数据和滚动加载的数据,用scan累积数组 this.dataList$ = merge(initialData$, scrollLoad$).pipe( scan((acc, curr) => [...acc, ...curr], []) ); } ngOnDestroy() { // 销毁组件时移除滚动监听,避免内存泄漏 window.removeEventListener('scroll', this.scrollEventHandler); } }
3. 关键注意事项
- 确保你的RxJS版本是6+,所有操作符都从
rxjs/operators导入,而不是旧的rxjs/add/operator/xxx方式。 - 服务方法绝对不能直接在内部调用
.subscribe(),必须返回Observable,这样组件才能链式处理数据流。 - 滚动监听要记得在组件销毁时移除,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Ahmet Ömer
相关产品推荐
相关产品推荐

