升级到 Angular 9 后,扩展通用 Firestore 服务时出错
Getting error in generic Firestore service while extending it, after upgrading to Angular 9
我有一个通用的 class,它包装了 Angular Firestore,然后我输入并扩展它以在我的应用程序中使用。升级到Angular9后,这个安排就不行了。要查看完整代码的来源,请参阅 https://www.toptal.com/angular/state-management-in-angular-using-firebase。
摘要class包装:
import { Inject } from '@angular/core';
import { AngularFirestore, QueryFn } from '@angular/fire/firestore';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { environment } from 'src/environments/environment';
export abstract class FirestoreService<T> {
protected abstract basePath: string;
constructor(
@Inject(AngularFirestore) protected firestore: AngularFirestore,
) {
}
collection$(queryFn?: QueryFn): Observable<T[]> {
return this.firestore.collection<T>(`${this.basePath}`, queryFn).valueChanges().pipe(
tap(r => {
if (!environment.production) {
console.groupCollapsed(`Firestore Streaming [${this.basePath}] [collection$]`);
console.table(r);
console.groupEnd();
}
}),
);
}
}
然后我将它扩展到:
import { Injectable } from '@angular/core';
import { FirestoreService } from 'src/app/core/services/firestore.service';
import { Employee } from '../models/employee';
@Injectable({
providedIn: 'root'
})
export class EmployeeFirestore extends FirestoreService<Employee> {
protected basePath: string = 'employees';
}
然后注入:
import { EmployeesPageStore } from './employees-page.store';
import { EmployeeFirestore } from './employee.firestore';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Employee } from '../models/employee';
import { tap, map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class EmployeesService {
constructor(
private firestore: EmployeeFirestore,
private store: EmployeesPageStore
) {
this.firestore.collection$().pipe(
tap(employees => {
this.store.patch({
loading: false,
employees,
totalEmployees: employees.length,
totalDrivers: employees.filter(employee => employee.hasDriverLicense).length,
totalRosarioEmployees: employees.filter(employee => employee.location === 'Rosario').length,
}, `employees collection subscription`);
})
).subscribe();
}
如前所述,这在 Angular 8 中运行良好,但在 Angular 9 中出现以下错误(在开发人员工具中):
ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'collection' of undefined
TypeError: Cannot read property 'collection' of undefined
at EmployeeFirestore.collection$ (firestore.service.ts:30)
at new EmployeesService (employees.service.ts:17)
at Object.EmployeesService_Factory [as factory] (employees.service.ts:119)
at R3Injector.hydrate (core.js:16765)
at R3Injector.get (core.js:16526)
at NgModuleRef.get (core.js:35567)
at Object.get (core.js:33358)
at getOrCreateInjectable (core.js:5470)
at Module.ɵɵdirectiveInject (core.js:20777)
at NodeInjectorFactory.EmployeesSummaryComponent_Factory [as factory] (employees-summary.component.ts:10)
at resolvePromise (zone-evergreen.js:793)
at resolvePromise (zone-evergreen.js:752)
at zone-evergreen.js:854
at ZoneDelegate.invokeTask (zone-evergreen.js:400)
at Object.onInvokeTask (core.js:40772)
at ZoneDelegate.invokeTask (zone-evergreen.js:399)
at Zone.runTask (zone-evergreen.js:168)
at drainMicroTaskQueue (zone-evergreen.js:570)
at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:485)
at invokeTask (zone-evergreen.js:1596)
此错误是由于抽象 class 构造函数中的 firestore 未初始化而引起的。我认为您不必这样做,这是某个地方的错误,但是如果您将 @Injectable() 装饰器添加到抽象 class,则 firestore 会在扩展 class 中正确启动。
我有一个通用的 class,它包装了 Angular Firestore,然后我输入并扩展它以在我的应用程序中使用。升级到Angular9后,这个安排就不行了。要查看完整代码的来源,请参阅 https://www.toptal.com/angular/state-management-in-angular-using-firebase。
摘要class包装:
import { Inject } from '@angular/core';
import { AngularFirestore, QueryFn } from '@angular/fire/firestore';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { environment } from 'src/environments/environment';
export abstract class FirestoreService<T> {
protected abstract basePath: string;
constructor(
@Inject(AngularFirestore) protected firestore: AngularFirestore,
) {
}
collection$(queryFn?: QueryFn): Observable<T[]> {
return this.firestore.collection<T>(`${this.basePath}`, queryFn).valueChanges().pipe(
tap(r => {
if (!environment.production) {
console.groupCollapsed(`Firestore Streaming [${this.basePath}] [collection$]`);
console.table(r);
console.groupEnd();
}
}),
);
}
}
然后我将它扩展到:
import { Injectable } from '@angular/core';
import { FirestoreService } from 'src/app/core/services/firestore.service';
import { Employee } from '../models/employee';
@Injectable({
providedIn: 'root'
})
export class EmployeeFirestore extends FirestoreService<Employee> {
protected basePath: string = 'employees';
}
然后注入:
import { EmployeesPageStore } from './employees-page.store';
import { EmployeeFirestore } from './employee.firestore';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Employee } from '../models/employee';
import { tap, map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class EmployeesService {
constructor(
private firestore: EmployeeFirestore,
private store: EmployeesPageStore
) {
this.firestore.collection$().pipe(
tap(employees => {
this.store.patch({
loading: false,
employees,
totalEmployees: employees.length,
totalDrivers: employees.filter(employee => employee.hasDriverLicense).length,
totalRosarioEmployees: employees.filter(employee => employee.location === 'Rosario').length,
}, `employees collection subscription`);
})
).subscribe();
}
如前所述,这在 Angular 8 中运行良好,但在 Angular 9 中出现以下错误(在开发人员工具中):
ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'collection' of undefined
TypeError: Cannot read property 'collection' of undefined
at EmployeeFirestore.collection$ (firestore.service.ts:30)
at new EmployeesService (employees.service.ts:17)
at Object.EmployeesService_Factory [as factory] (employees.service.ts:119)
at R3Injector.hydrate (core.js:16765)
at R3Injector.get (core.js:16526)
at NgModuleRef.get (core.js:35567)
at Object.get (core.js:33358)
at getOrCreateInjectable (core.js:5470)
at Module.ɵɵdirectiveInject (core.js:20777)
at NodeInjectorFactory.EmployeesSummaryComponent_Factory [as factory] (employees-summary.component.ts:10)
at resolvePromise (zone-evergreen.js:793)
at resolvePromise (zone-evergreen.js:752)
at zone-evergreen.js:854
at ZoneDelegate.invokeTask (zone-evergreen.js:400)
at Object.onInvokeTask (core.js:40772)
at ZoneDelegate.invokeTask (zone-evergreen.js:399)
at Zone.runTask (zone-evergreen.js:168)
at drainMicroTaskQueue (zone-evergreen.js:570)
at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:485)
at invokeTask (zone-evergreen.js:1596)
此错误是由于抽象 class 构造函数中的 firestore 未初始化而引起的。我认为您不必这样做,这是某个地方的错误,但是如果您将 @Injectable() 装饰器添加到抽象 class,则 firestore 会在扩展 class 中正确启动。