Ваше решение, как правило, хорошее. Существует вероятность появления странных ошибок, поскольку MODAL_YES_CLICKED
всегда прослушивается, даже если уведомление не отображается, хотя вопрос о том, является ли это спорным.
Когда мне нужны похожие шаблоны, я лично настраиваю слушателя только по мере необходимости и проверяю, есть ли способ отменить (например, MODAL_NO_CLICKED
), чтобы не допустить утечки памяти. Более последовательное выражение этого помогает мне понять ожидаемый поток.
return action$.pipe(
ofType(NOTIFICATION_DELETE_REQUEST),
switchMap(action => {
uid = shortid.generate();
return action$.pipe(
ofType(MODAL_YES_CLICKED),
filter(({ payload }) => payload.uid === uid),
take(1),
mergeMap(({ payload }) =>
deleteNotification$(payload.notificationId, dependencies).pipe(
map(() => deleteNotificationSuccess()),
catchError(error => of(deleteNotificationSuccess(error))),
),
),
takeUntil(action$.pipe(ofType(MODAL_NO_CLICKED))),
startWith(
showYesNo({
message: 'NOTIFICATION_DELETE_CONFIRMATION',
payload: {
notificationId: action.notificationId,
uid,
},
})
)
)
}),
)
Одна интересная вещь в моем подходе к вашему - это то, что мой немного более многословен, потому что мне нужно иметь takeUntil
, а также take(1)
(чтобы мы не пропускали память).
Юнит-тест:
it('should delete the notification when MODAL_YES_CLICKED is dispatched', () => {
const uid = 1234;
shortid.generate.mockImplementation(() => uid);
const store = null;
const dependencies = {
ajax: () => of({}),
uid,
};
const inputValues = {
a: action.deleteNotificationRequest(12345, uid),
b: buttonYesClicked({ id: 12345, uid }),
};
const expectedValues = {
a: showYesNo({
message: 'NOTIFICATION_DELETE_CONFIRMATION',
payload: {
id: 12345,
uid,
},
}),
b: showToastSuccessDeleted(),
c: action.loadNotificationsRequest(false),
};
const inputMarble = ' a---b';
const expectedMarble = '---a---(bc)';
const ts = new TestScheduler((actual, expected) => {
expect(actual).toEqual(expected);
});
const action$ = new ActionsObservable(ts.createHotObservable(inputMarble, inputValues));
const outputAction = epic.deleteNotificationEpic(action$, store, dependencies);
ts.expectObservable(outputAction).toBe(expectedMarble, expectedValues);
ts.flush();
});