Question: actor with promise doesn't return output? #4632
-
Hi all! I created a simple FSM with XState 5.3.1. It has an actor that uses a promise. I'm now trying to create a test for it, using ESM + Vitest 1.1.0. However, my FSM doesn't run properly - it doesn't return the expected output. I'm overlooking something. Can you help? My code: import {createActor, fromPromise, setup} from 'xstate';
const work = fromPromise(async () => {
console.log('Start work');
console.log('End work');
});
const finish = fromPromise(async () => {
console.log('Finish');
});
export async function run() {
const main = setup({
actors: {
work,
finish,
},
}).createMachine({
id: 'main',
initial: 'work',
states: {
work: {
invoke: {
id: 'work',
src: 'work',
onDone: 'finish',
},
},
finish: {
invoke: {
id: 'finish',
src: 'finish',
onDone: 'done',
},
},
done: {
type: 'final',
},
},
});
createActor(main).start();
} My test: import {run} from './state.js';
import {describe, it} from 'vitest';
describe('run', () => {
it('runs', async () => {
await run();
});
}); ... then my test logs 'Start work', 'End work' and 'Finish' -- perfect! However, if I change the code to: import {setTimeout} from 'timers/promises'; // ---> New
import {createActor, fromPromise, setup} from 'xstate';
const work = fromPromise(async () => {
console.log('Start work');
await setTimeout(1000); // ---> New: some promise
console.log('End work');
});
const finish = fromPromise(async () => {
console.log('Finish');
});
export async function run() {
const main = setup({
actors: {
work,
finish,
},
}).createMachine({
id: 'main',
initial: 'work',
states: {
work: {
invoke: {
id: 'work',
src: 'work',
onDone: 'finish',
},
},
finish: {
invoke: {
id: 'finish',
src: 'finish',
onDone: 'done',
},
},
done: {
type: 'final',
},
},
});
createActor(main).start();
} ... then my test logs 'Start work', but not 'End work' and 'Finish'. Can you see why? Thanks a lot! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
There is nothing that's "awaiting" that promise - You can use the import {
toPromise,
// ...
} from 'xstate';
// ...
export async function run() {
// ...
const actor = createActor(main);
actor.start();
await toPromise(actor);
} See the docs for more info. |
Beta Was this translation helpful? Give feedback.
There is nothing that's "awaiting" that promise -
createActor(main).start()
will just return immediately.You can use the
toPromise(...)
helper:See the docs for more info.