I’m in need of some advice on reconciling those few things to complete a task in my application. I have a pretty solid understanding of the concepts individually but am struggiling with gettting them all to work together in this instance.
It seems to me that it’s a matter of timing. The process goes like this, with the gist of the code included.
- I have a query function that I call from a provider.
this._categoryLevelTerm$
is a Behavior Subject that I use as my search term in that provider. The function works fine.
// MY PROVIDER
searchCategoryItemsByLevel(term: string | null): void {
this._categoryLevelTerm$.next(term);
}
queryCategoryItems(uid: string): Observable<ItemElement[]> {
return this.categoryLevelTerm$.pipe(
switchMap((term) => this.fs.collection<string>('users').doc(uid).collection<ItemElement>('item_elements', ref => {
let query: firebase.firestore.CollectionReference | firebase.firestore.Query = ref;
if (term) { query = query.where('_level', '==', term)}
return query;
}).valueChanges())
)
}
- I enter a page in my app and subscribe to the query on enter. Also no problem here. The results come through, I do a few necessary things with the value of the result and all is well.
// MY COMPONENT
ionViewDidEnter() {
this.database.queryCategoryItems(this.uid).pipe(takeUntil(this.destroy$))
.subscribe(result => {
// I do a few things with my result
}
}
-
From my page, I call the function that changes the search term in my provider from 3 seperate functions in my component. Each provides a different search term, so the subscription updates with each term. Works just fine. The problem comes when I follow up with a function that depends on the result of that subscription and involves Promises.
What’s obviously happening is that the Promise chain completes before the subscription updates so it’s using the previous result as the necessary parameter. I click the button once and it’s using the previous resutls, then on click 2 it uses the results that I expected to recieve on click 1.
A representation of the process
// ALSO CALLED FROM MY COMPONENT
searchBasic() {
this.database.searchCategoryByTitle(this.BASIC_TAG);
/* results of the subscription are stored in this.subscriptionResult */
this.reduceItems(this.subscriptionResult)
.then((results) => this.finishFunction(results))
}
searchProfessional() {
this.database.searchCategoryByTitle(this.PROFESSIONAL_TAG)
this.reduceItems(this.subscriptionResult)
.then((results) => this.finishFunction(results))
}
At the moment, this.reduceItems(this.subscriptionResult)
is returning
Observable.of(this.reducedItems).toPromise();
This is the latest in my attempts to reconcile that race condition. I have tried transforming this.subscriptionReult
itself, assigning the result to a locally created variable and returning that, etc.
Nothing is working which leads me to the belief that nothing WILL work unless I ensure the subscription updates before the Promise chain begins.
I glossed over some stuff because it’s wordy, and I don’t think anything I left out will change the fact that the subscription needs to update before anything else happens.
More info available on request!
If anyone has any advice, I would appreciate it very much. I’m hoping there’s a way to ensure that the subscription updates, then begin the promise chain. But I realize I may have to fundamentally change the way I’m going about this.