Skip to content

Commit

Permalink
fix: series with duplicated values (#2841)
Browse files Browse the repository at this point in the history
  • Loading branch information
johnthecat authored Dec 11, 2024
1 parent 32e8b1d commit 1f06765
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 5 deletions.
21 changes: 21 additions & 0 deletions src/renderer/shared/effector/helpers/series.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { createEvent, createWatch } from 'effector';

import { series } from './series';

describe('series', () => {
it('should spread array into events', () => {
const spy = jest.fn();
const targetEvent = createEvent<number>();
const wrappedEvent = series(targetEvent);

createWatch({
unit: targetEvent,
fn: spy,
});

wrappedEvent([1, 2, 2, 3, 3, 3]);

expect(spy).toHaveBeenCalledTimes(6);
expect(spy.mock.calls).toEqual([[1], [2], [2], [3], [3], [3]]);
});
});
16 changes: 11 additions & 5 deletions src/renderer/shared/effector/helpers/series.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type Effect, type Event, type EventCallable, createEvent, createStore, sample } from 'effector';
import { type Effect, type EventCallable, createEvent, createStore, sample } from 'effector';

import { nonNullable } from '@/shared/lib/utils';
import { nonNullable, nullable } from '@/shared/lib/utils';

/**
* Triggers target unit on each element of the input list.
Expand All @@ -24,13 +24,19 @@ export const series = <T>(target: EventCallable<T> | Effect<T, any>) => {
const push = createEvent<Iterable<T> | ArrayLike<T>>();

const $queue = createStore<T[]>([])
.on(push, (state, payload) => state.concat(Array.from(payload)))
.on(push, (state, payload) => state.concat(Array.isArray(payload) ? payload : Array.from(payload)))
.on(pop, ([, ...rest]) => rest);
const $head = $queue.map((queue) => queue.at(0) ?? null);
const nextHeadRetrieved = $head.updates.filter({ fn: nonNullable }) as Event<T>;
const $head = $queue.map((queue) => {
const value = queue.at(0);
if (nullable(value)) return null;

return { value };
});
const nextHeadRetrieved = $head.updates.filter({ fn: nonNullable });

sample({
clock: nextHeadRetrieved,
fn: ({ value }) => value,
target: [target, pop],
});

Expand Down

0 comments on commit 1f06765

Please sign in to comment.