Как RxFire обрабатывает запросы к хранилищу огня
Этот js reduce отлично справляется с обработкой результата запроса:
function toc(current) {
return {....};
};
function getToc(data) {
return = data.reduce((a, c) => Object.assign(a, {[c.id]: toc(c)}), {});
};
const query = db.collection(normCollection)
.where('a_id', '==', a_id )
.where('year', '==', year)
.orderBy("id");
subscriptionNorm = collectionData(query, "id")
.subscribe(data => console.log(getToc(data)));
Но когда я использую RxJs reduce, он перестает работать. Это как-то связано с концом потока, но... Но я не понимаю, как RxFire / RxJs обрабатывает результат потокового запроса firestore:
...
subscriptionNorm = collectionData(query, "id")
.pipe(reduce((a, c) => Object.assign(a, {[c.id]: toc(c)}), {}))
.subscribe(data => console.log(data));
Обновите это работает нормально, но...:
...
subscriptionNorm = collectionData(query, "id")
.pipe(
map(v => v.reduce((a, c) =>
Object.assign(a, {[c.id]: toc(c)}), {})
),
)
.subscribe(data => console.log(data));
1 ответ
Ваше предположение относительно оператора сокращения rxjs верное.
"Применяет функцию накопителя к исходному Observable и возвращает накопленный результат, когда источник завершается" - из документации, см. Здесь: RxJS reduce docs
В вашем случае источник не будет завершен, потому что именно так работает Firestore, он работает бесконечно без завершения, пока не произойдет ошибка или вы не откажетесь от подписки вручную.
В качестве грубого примера вы можете использовать
take(1)
внутри канала, и он завершит источник Observable после генерации 1 события, таким образом,
reduce
будет работать, но убивает основную идею Firestore Observable.
Вот как вы можете использовать rxjs
reduce
оператор:
subscriptionNorm = collectionData(query, "id").pipe(
switchMap(data => from(data).pipe(
reduce((a, c) => Object.assign(a, { [c.id]: toc(c) }), {})
)),
).subscribe(data => console.log(data));
Это возможно, потому что я переключаюсь на
from(data)
и внутренний Observable будет завершен, поэтому
reduce
оператор будет работать так, как вы задумали.
Но, честно говоря, это перебор, и вы можете просто сохранить то, что уже реализовали:
subscriptionNorm = collectionData(query, "id").pipe(
map(data => data.reduce((a, c) => Object.assign(a, { [c.id]: toc(c) }), {}))),
).subscribe(data => console.log(data));