我具有以下提供程序工厂,用于动态计算的Firebase Firestore路径:
const meetingServiceFactory = (db: AngularFirestore, authService: AuthService ) => {
const userId = authService.user;
return new MeetingService('/users/' + userId + '/meetings', db);
};
export let meetingServiceProvider = { provide: MeetingService,
useFactory: meetingServiceFactory,
deps: [AngularFirestore, AuthService] };
这里是MeetingService
:
@Injectable(
{
providedIn: 'root'
}
)
export class MeetingService extends FirestoreDataService<Meeting> {
constructor(path: string, db: AngularFirestore) {
super(path, db);
}
setProposalFlag(meetingKey: string) {
return from(this.db.doc(this.path + `/${meetingKey}`).update({hasProposal: true})
.then(result => console.log('changed active Flag on meeting: ', result))
.catch(err => console.log(err)));
}
saveMeeting(meeting: Meeting) {
return of(meeting).pipe(
map(meetingToSave => {
return {...meetingToSave, key: this.db.createId() };
}),
switchMap( finalMeeting => this.addItemWithKey(finalMeeting.key, finalMeeting) )
);
}
getAll() {
return this.getItems();
}
}
这是从FirestoreDataService<T>
继承的,因此我可以重用一种CRUD服务:
@Injectable()
export class FirestoreDataService<T> {
protected itemCollection: AngularFirestoreCollection<T>;
protected items$: Observable<T[]>;
protected snapshot$: Observable<DocumentChangeAction<T>[]>;
protected state$: Observable<DocumentChangeAction<T>[]>;
constructor(protected path: string, protected db: AngularFirestore) {
this.itemCollection = this.db.collection<T>(path);
this.items$ = this.itemCollection.valueChanges();
this.snapshot$ = this.itemCollection.snapshotChanges();
this.state$ = this.itemCollection.stateChanges();
}
getItems(): Observable<T[]> {
return this.items$;
}
getItemWithKey( key: string): Observable<T> {
// used to use stateChanges here.
// as the doc states, this only emits recent changes,
// so if we subscribe in an async pipe, it will not reemit and subsequent observables will be empty.
return this.itemCollection.doc<T>(key).valueChanges();
}
addItem(data: T) {
return from(this.itemCollection.add(data)
.catch(err => console.log('Error while adding item: ', err)));
}
addItemWithKey(key: string, data: T) {
return from(this.itemCollection.doc(key).set(data)
.catch(err => console.log('Error while adding item: ', err)));
}
deleteItem(key: string) {
return from(this.itemCollection.doc(key).delete()
.catch(err => console.log('Error while deleting item: ', err)));
}
}
,但这显然取决于userId的运行时决策。似乎可以在ng serve
内正常工作,但在为产品转译时,我得到:ERROR in : Can't resolve all parameters for FirestoreDataService in /web-client/src/app/core/services/firestore-data.service.ts: (?, [object Object]).
我认为那是因为我在编译时不知道确切的路径。是这样吗?如果没有,此设置可能是什么问题?以及我将如何解决/改善它?我现在运行Angular 7。感谢您的帮助!
答案 0 :(得分:0)
我通过重构解决了这个问题。希望对某人有用。
如果有人感兴趣,这就是我重构会议服务的方式:
@Injectable(
{
providedIn: 'root'
}
)
export class MeetingService extends FirestoreDataService<Meeting> {
constructor(authService: AuthService,
db: AngularFirestore) {
const path = `/users/${authService.user}/meetings`;
super(path, db);
this.auth = authService;
}
...
}
请注意,这仅适用于因为以这种方式注入服务,参数是构造函数专用的,否则,第一个调用必须为super(path, db);