gpt4 book ai didi

具有动态参数的 Angular Factory Provider

转载 作者:搜寻专家 更新时间:2023-10-30 21:56:18 25 4
gpt4 key购买 nike

我有以下提供程序工厂用于动态计算的 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。感谢您的帮助!

最佳答案

我通过重构解决了这个问题。希望它对某人有用。

  1. Angular docs on DI提供有关如何使用注入(inject)器的大量文档,这在测试中也很有用。
  2. 但是,没有关于我的确切用例的描述,因为 DI 需要在转译时定义参数。将其与框架进行比较,例如Spring,您可以在上下文启动时进行值注入(inject)。傻老头以为这里也一样,不过当然,连Spring在启动的时候也需要定义bean。
  3. 因此,当转译器(包括 aot)无法决定参数的来源时,它会抛出错误。

如果有人感兴趣,下面是我重构 MeetingService 的方式:

@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;
}

...

}

请注意,这只有效,因为以这种方式注入(inject)服务,参数对构造函数是私有(private)的,否则,第一次调用必须是 super(path, db);

关于具有动态参数的 Angular Factory Provider,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55282665/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com