Reputation: 460
I have my auth function using rxjs epics:
export const authWithEmailPasswordEpic = action$ =>
action$.pipe(
filter(authUser.match),
switchMap(({payload}) =>
defer(() =>
from(firebaseEmailPasswordAuth(payload)).pipe(
mergeMap(() => of(clearAlertState(), stopLoading())),
catchError(err =>
of(clearState(), createAlert({
status: err.code,
alertType: RED_ALERT,
alertTitle: err.message
})),
)
)
)
)
);
If the users credentials are incorrect, I am dispatching an alert, but then I also want to remove the alert after 5 seconds or so. Therefore, I believe I'd need to emit two actions to achieve this, with the second one being:
of(toggleAlert()).pipe(delay(5000)))
How would I achieve this or is there a better way to do so?
Upvotes: 2
Views: 397
Reputation: 6716
You can achieve that using delay(5000)
after catchError
, then mergeWith
the of(toggleAlert())
, like the following:
export const authWithEmailPasswordEpic = action$ =>
action$.pipe(
filter(authUser.match),
switchMap(({ payload }) =>
defer(() =>
from(firebaseEmailPasswordAuth(payload)).pipe(
mergeMap(() => of(clearAlertState(), stopLoading())),
catchError(err =>
of(
clearState(),
createAlert({
status: err.code,
alertType: RED_ALERT,
alertTitle: err.message
})
)
),
mergeWith(of(toggleAlert()).pipe(delay(5000)))
)
)
)
);
Upvotes: 1
Reputation: 3409
You're on the right track... For a simpler version I would use concat
, I think it reads better:
export const authWithEmailPasswordEpic = (action$) =>
action$.pipe(
filter(authUser.match),
switchMap(({ payload }) =>
from(firebaseEmailPasswordAuth(payload)).pipe(
mergeMap(() => of(clearAlertState(), stopLoading())),
catchError((err) =>
concat(
[
clearState(),
createAlert({
status: err.code,
alertType: RED_ALERT,
alertTitle: err.message,
}),
],
timer(5000).pipe(
mapTo(toggleAlert())
)
)
)
)
)
);
With this pattern you can then make it fancier. Imagine you want to dispatch toggleAlert
except if the user has made Action.CloseAlert
. Then you can swap that timer.pipe for:
timer(5000).pipe(
mapTo(toggleAlert()),
takeUntil(action$.pipe(
filter((action) => action.type === Action.CloseAlert)
))
);
Another note - I don't think that defer()
is needed here. switchMap immediately subscribes to the result fo the function, so it shouldn't really matter. Add it back if you need it
Upvotes: 1