Skip to content

Commit 1fc7737

Browse files
ehuelsmannkybargedwardsnjd
authored
Invoke promise fix (#208)
* fix: do not fire promise events after state changes * chore: update tests * Add a changeset Create odd-lizards-guess.md * Fix typo Co-authored-by: edwardsnjd <[email protected]> * Fix typo Co-authored-by: edwardsnjd <[email protected]> --------- Co-authored-by: Ruslan Kyba <[email protected]> Co-authored-by: edwardsnjd <[email protected]>
1 parent c953ce8 commit 1fc7737

File tree

3 files changed

+58
-2
lines changed

3 files changed

+58
-2
lines changed

.changeset/odd-lizards-guess.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"robot3": patch
3+
---
4+
5+
Don't make a state transition if the state is left before the invoked promise resolves, *even* if there's a transition with the same name.

packages/core/machine.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,15 @@ let invokeFnType = {
8989
machine: valueEnumerable(rn),
9090
transitions: valueEnumerable(this.transitions)
9191
}).enter(machine2, service, event)
92-
rn.then(data => service.send({ type: 'done', data }))
93-
.catch(error => service.send({ type: 'error', error }));
92+
rn
93+
.then(data => {
94+
if (machine2 === service.machine)
95+
return service.send({ type: 'done', data });
96+
})
97+
.catch(error => {
98+
if (machine2 === service.machine)
99+
return service.send({ type: 'error', error });
100+
});
94101
return machine2;
95102
}
96103
};

packages/core/test/test-invoke.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,50 @@ QUnit.module('Invoke', hooks => {
5252
assert.equal(service.machine.current, 'two', 'in the new state');
5353
});
5454

55+
QUnit.test('Should not fire "done" event when state changes', async assert => {
56+
const wait = ms => () => new Promise(resolve => setTimeout(resolve, ms));
57+
58+
let machine = createMachine({
59+
one: state(transition('click', 'two')),
60+
two: invoke(wait(10),
61+
transition('done', 'one'),
62+
transition('click', 'three')
63+
),
64+
three: state(
65+
transition('done', 'error'),
66+
),
67+
error: state(),
68+
});
69+
70+
let service = interpret(machine, () => { });
71+
service.send('click');
72+
service.send('click');
73+
await wait(15)()
74+
assert.equal(service.machine.current, 'three', 'now in the next state');
75+
});
76+
77+
QUnit.test('Should fire "done" when context changes', async assert => {
78+
const wait = ms => () => new Promise(resolve => setTimeout(resolve, ms));
79+
80+
let machine = createMachine({
81+
one: state(transition('click', 'two')),
82+
two: invoke(wait(10),
83+
transition('done', 'three'),
84+
transition('click', 'two', reduce((ctx) => ({ value: ctx.value + 1 })))
85+
),
86+
three: state(),
87+
error: state(),
88+
}, () => ({ value: 0 }));
89+
90+
let service = interpret(machine, () => { });
91+
service.send('click');
92+
service.send('click');
93+
service.send('click');
94+
await wait(15)()
95+
assert.equal(service.context.value, 2, 'value should be 2');
96+
assert.equal(service.machine.current, 'three', 'now in the correct state');
97+
});
98+
5599
QUnit.module('Machine');
56100

57101
QUnit.test('Can invoke a child machine', async assert => {

0 commit comments

Comments
 (0)