I come from an Angular background switching over to Blazor. Since I like the redux pattern and have used NGRX with Angular, I'm using Blazor Fluxor for statement management, which works well.
Now I want to use Observables in my effects when calling my database instead of Tasks. While I've learned from here how to wrap HTTP requests into Observables, I am unsure on how to tie this in with Fluxor (which I've heard, uses Observables under the hood, is that right?).
My main reason for wanting to do this is, that I want to minimise unnecessary database calls. E.g. I'm dispating actions to load data from the database on navigating to different pages. If the loading takes a long time and the user navigates away from and back to the page, a second action is dispatched, querying the database for the same data, in parallel to the first query. In RXJS, I would have used the exhaustMap operator to ignore those requests until the preceeding request completes.
In Angular, I would have done something like this
export const getAnimalsEffect = createEffect((actions$ = inject(Actions)) => {
const gql = inject(GetAnimalsGQL); // <-- service which makes http requests
return actions$.pipe(
ofType(AnimalsPageActions.getAnimals),
exhaustMap(() => gql.fetch().pipe(
map(animalsQueryResult => animalsQueryResult.data.animals.map(m => m as IAnimal)),
map(animals => AnimalsApiActions.getAnimalsSuccess(animals)),
catchError(e => of(AnimalsApiActions.getAnimalsFailure(e)))
))
)}, { functional: true }
);
In Fluxor, this currently looks like this
public class AnimalsEffects(IState<AnimalsState> state, IGqlClient client)
{
[EffectMethod] public async Task OnGetAnimals(GetAnimals action, IDispatcher dispatcher)
{
try
{
var result = await client.GetAnimals.ExecuteAsync(); // <-- http request
dispatcher.Dispatch(new GetAnimalsSuccess(result.Data!));
}
catch (Exception ex)
{
dispatcher.Dispatch(new GetAnimalsFailure(ex.Message));
}
}
}
Do you have any starters for me? As far as I know, the effect method must return a task, so just wrapping the request in Observable.FromAsync() wont work.