Как 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));
Другие вопросы по тегам