Как добавить автоинкрементные идентификаторы в наблюдаемый массив с динамическим размером?

Я использую callbags, но логика та же, что и в RxJS.

Я делаю наблюдаемый список, который можно добавлять и удалять. Я хочу иметь автоинкрементные идентификаторы. Я не знаю правильной логики для прикрепления идентификаторов к элементам.

Вот упрощенный пример с добавлением событий:

import { flatten, map, merge, pipe, scan } from 'callbag-basics';
import just from 'callbag-of';
import remember from 'callbag-remember';
import subscribe from 'callbag-subscribe';

const addEvents = remember(just('add-event', 'add-event')); // remember is shareReplay(1)
const itemIds = pipe(
  addEvents,
  scan((acc) => acc + 1, 1),
);
const initialReducers = just(() => [{ id: 1, data: 'foo' }]);
const addReducers = pipe(
  addEvents,
  map(() => pipe(
    itemIds,
    map((id) => ({ id, data: 'bar' })),
  )),
  flatten,
  map((item) => (prevState) => prevState.concat(item)),
);
const reducers = merge(initialReducers, addReducers);
const states = pipe(
  reducers,
  scan((acc, reducer) => reducer(acc), null),
);

pipe(
  states,
  subscribe((state) => {
    // Expected
    // [{ id: 1, data: 'foo' }]
    // [{ id: 1, data: 'foo' }, { id: 2, data: 'bar'}]
    // [{ id: 1, data: 'foo' }, { id: 2, data: 'bar'}, { id: 3, data: 'bar'}]
    console.log(state);
    // Actual
    // [{ id: 1, data: 'foo' }]
    // [{ id: 1, data: 'foo' }, { id: 2, data: 'bar'}]
    // [{ id: 1, data: 'foo' }, { id: 2, data: 'bar'}, { id: 2, data: 'bar'}]
    // [{ id: 1, data: 'foo' }, { id: 2, data: 'bar'}, { id: 2, data: 'bar'}, { id: 3, data: 'bar'}]
  }),
);

Идентификатор начинается с начала для каждого дополнительного элемента. Вместо этого я хочу, чтобы идентификаторы соответствовали количеству добавленных элементов. По сути, проблема заключается в привязке промежуточного итога событий к преобразованию данных события. Как добавить автоинкрементные идентификаторы в наблюдаемый массив с динамическим размером?

Не нужно помещать ответ в форму коллбэгов. Я умею читать RxJS. Спасибо.

Изменить: я установил RxJS, чтобы преобразовать пример:

const rxjs = require('rxjs');
const { map, mergeMap, scan, shareReplay } = require('rxjs/operators');

const addEvents = rxjs.of('add-event', 'add-event').pipe(
  shareReplay(1),
);
const itemIds = addEvents.pipe(
  scan((acc) => acc + 1, 1),
);
const initialReducers = rxjs.of(() => [{ id: 1, data: 'foo' }]);
const addReducers = addEvents.pipe(
  mergeMap(() => itemIds.pipe(
    map((id) => ({ id, data: 'bar' })),
  )),
  map((item) => (prevState) => prevState.concat(item)),
);
const reducers = rxjs.merge(initialReducers, addReducers);
const states = reducers.pipe(
  scan((acc, reducer) => reducer(acc), null),
);

states.subscribe((state) => {
  // Expected
  // [{ id: 1, data: 'foo' }]
  // [{ id: 1, data: 'foo' }, { id: 2, data: 'bar'}]
  // [{ id: 1, data: 'foo' }, { id: 2, data: 'bar'}, { id: 3, data: 'bar'}]
  console.log(state);
  // Actual
  // [{ id: 1, data: 'foo' }]
  // [{ id: 1, data: 'foo' }, { id: 2, data: 'bar'}]
  // [{ id: 1, data: 'foo' }, { id: 2, data: 'bar'}, { id: 2, data: 'bar'}]
  // [{ id: 1, data: 'foo' }, { id: 2, data: 'bar'}, { id: 2, data: 'bar'}, { id: 3, data: 'bar'}]
});

person Eva    schedule 28.11.2020    source источник


Ответы (1)


Не знаком с библиотекой callbag, но пытались ли вы сделать:

  map(() => pipe(
   itemIds,
   map((id,index) => ({ id + index, data: 'bar' })),
  )),
person Tomas Gonzalez    schedule 28.11.2020
comment
Я не хочу использовать индекс. В реальном коде я также удаляю элементы. Индекс создавал бы дубликаты, если бы я зависел от него. Мне нужно отслеживать полное количество событий. - person Eva; 28.11.2020