Open Hurtak opened 1 year ago
For anyone that would encounter the same problem, we managed to workaround this with introduction our own version of invoke
import { invoke, Machine, MachineState, Service, Transition } from 'robot3';
const invokeFnType: {
enter: (machine2: Machine, service: Service<Machine>, event?: unknown) => Machine;
// fn is inherited so it should always be defined
fn?: (ctx: Machine['context'], event?: unknown) => Promise<unknown>;
} = {
enter(machine2: Machine, service: Service<Machine>, event?: unknown) {
// Only invoke the function if the machine state changed
if (machine2.current !== service.machine.current) {
this.fn
?.call(service, service.context, event)
.then((data: unknown) => service.send({ type: 'done', data }))
.catch((error: unknown) => service.send({ type: 'error', error }));
}
return machine2;
},
};
// Only invoke the async function (and the done/error transition) when transitioning into the state from other state,
// Do not invoke when transitioning from the same state (this is the only difference between invoke and this function)
export const invokeExceptForSelfTransitions = <C, T>(
fn: (ctx: C, event?: unknown) => Promise<T>,
...args: Transition[]
): MachineState => ({
...invoke(fn, ...args),
...invokeFnType,
});
Updating the context with regular
state(...)
is easy, you just do it inside oftransition
withreduce
, eg.:Now here is my problem (or perhaps some misunderstanding) - how do I do the same thing for invoke? What if I need some other transitions to update the context while the invoke is running?
For example I have machine which loads data to display in panel, and in the machine there is state for the data and for the panel opened/closed state - and I want to be able to toggle the panel while the data is loading. Here is how I implemented it so far: