Я слежу за этим вопросом , чтобы создать запрос, который извлекает один случайный элемент из коллекции Firebase в приложении Angular 9, используя AngularFire.
Решение отлично работает, и я получаю ожидаемый результат, кроме случаев, когда запрос возвращает 0 результатов. Если это произойдет, я хочу повторить запрос, меняя некоторые параметры, пока не получу один элемент, и только потом верну наблюдаемую, на которую можно подписаться в других сервисах. Я изучаю, как использовать Observables и Rx JS 6 операторов, и я думаю, что мне нужен оператор expand
. Однако я не могу предотвратить выход expand
из рекурсивного l oop, пока не достигну желаемого результата.
Это мой код:
random-query. service.ts
fetchDocumentoAleatorio(coleccionPath: string): Observable<any> {
const IdRandom = this.db.createId();
return this.consultaAleatorio(coleccionPath, '>=', IdRandom)
.pipe(expand((document: any) => document === null ? this.consultaAleatorio(coleccionPath, '<=', IdRandom) : EMPTY
), // I expect to repeat the query here changing '>=' to '<=' and using the same randomly generated Id
map((document) => { // The recursive loop never takes place since the map operator triggers even if consultaAleatorio() returns null one single time, sending that result to the subscribers
return publicacion.payload.doc.data();
}
));
}
consultaAleatorio(path: string, operador: any, idRandom: string): Observable<any> {
return this.db
.collection(path, ref => {
let query: firebase.firestore.CollectionReference | firebase.firestore.Query = ref;
query = query.where('random', operador, idRandom);
query = query.orderBy('random');
query = query.limit(1);
return query;
}).snapshotChanges()
.pipe(map((arrayDatos: any) => {
if (arrayDatos && arrayDatos.length) {
return arrayDatos[0];
} else {
return null; // It indeed reaches this point if the query returns empty results
}
}));
}
Если какой-либо другой сервис использует этот код, он делает это следующим образом:
subscriber-example-service.ts
private firebaseSubscriptions: Subscription [] = [];
publicacionAleatoriaSubject = new Subject<IpublicacionMiniatura>();
private publicacionAleatoria: IpublicacionMiniatura;
constructor(
private db: AngularFirestore,
private randomQueryService: RandomQueryService) {
}
fetchPublicacionAleatoria(): void {
this.firebaseSubscriptions.push(this.randomQueryService.fetchDocumentoAleatorio('publicaciones-meta')
.pipe(map((publicacion) => {
return {
//processes data
};
})
)
.subscribe((publicacionAleatoria: IpublicacionMiniatura) => {
this.publicacionAleatoria = publicacionAleatoria;
this.publicacionAleatoriaSubject.next(this.publicacionAleatoria);
}
));
В сумме:
- Рекурсивный l oop никогда не выполняется, поскольку оператор
map
срабатывает, даже если consultaAleatorio()
возвращает null
один раз, отправка этого результата подписчикам - Когда я подписываюсь на это Observable в других службах, он работает гладко и, как и ожидалось, за исключением описанного случая, поэтому я думаю, что проблема заключается в моем непонимании того, как обрабатывать
expand
оператор для достижения того, что мне нужно.
Заранее благодарим за ваше время.