Skip to content

Commit fa50f43

Browse files
fix(signals): handle events in the dispatched order (#4857)
Closes #4852
1 parent 0ae48c3 commit fa50f43

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

modules/signals/events/spec/integration.spec.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { fakeAsync, TestBed, tick } from '@angular/core/testing';
33
import {
44
delay,
55
exhaustMap,
6+
map,
67
mergeMap,
78
Observable,
89
of,
@@ -25,6 +26,8 @@ import {
2526
withEntities,
2627
} from '@ngrx/signals/entities';
2728
import {
29+
Dispatcher,
30+
event,
2831
eventGroup,
2932
Events,
3033
injectDispatch,
@@ -230,6 +233,53 @@ describe('Integration Tests', () => {
230233
});
231234
expect(console.error).toHaveBeenCalledWith('Error!');
232235
}));
236+
237+
it('handles events in the order they are dispatched', () => {
238+
const handledEventsLog: string[] = [];
239+
const first = event('first');
240+
const second = event('second');
241+
const save = event('save', type<string>());
242+
const Store = signalStore(
243+
{ providedIn: 'root' },
244+
withState({ savedEvents: [] as string[] }),
245+
withEffects((_, events = inject(Events)) => ({
246+
emitSecond$: events.on(first).pipe(
247+
tap(({ type }) =>
248+
handledEventsLog.push(`emitSecond$ effect: ${type}`)
249+
),
250+
map(() => second())
251+
),
252+
save$: events.on(first, second).pipe(
253+
tap(({ type }) => handledEventsLog.push(`save$ effect: ${type}`)),
254+
map(({ type }) => save(type))
255+
),
256+
})),
257+
withReducer(
258+
on(first, second, save, ({ type, payload }) => {
259+
handledEventsLog.push(`reducer: ${type}${payload ?? ''}`);
260+
return {};
261+
}),
262+
on(save, ({ payload }, state) => ({
263+
savedEvents: [...state.savedEvents, payload],
264+
}))
265+
)
266+
);
267+
268+
const dispatcher = TestBed.inject(Dispatcher);
269+
const store = TestBed.inject(Store);
270+
271+
dispatcher.dispatch(first());
272+
expect(store.savedEvents()).toEqual(['first', 'second']);
273+
expect(handledEventsLog).toEqual([
274+
'reducer: first',
275+
'emitSecond$ effect: first',
276+
'reducer: second',
277+
'save$ effect: first',
278+
'reducer: savefirst',
279+
'save$ effect: second',
280+
'reducer: savesecond',
281+
]);
282+
});
233283
});
234284

235285
describe('custom withReducer and withEffects', () => {

modules/signals/events/src/dispatcher.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { inject, Injectable } from '@angular/core';
2+
import { queueScheduler } from 'rxjs';
23
import { EventInstance } from './event-instance';
34
import { Events, EVENTS, ReducerEvents } from './events-service';
45

@@ -32,6 +33,6 @@ export class Dispatcher {
3233

3334
dispatch(event: EventInstance<string, unknown>): void {
3435
this.reducerEvents[EVENTS].next(event);
35-
this.events[EVENTS].next(event);
36+
queueScheduler.schedule(() => this.events[EVENTS].next(event));
3637
}
3738
}

0 commit comments

Comments
 (0)