xstate - 如何正确处理转换错误?
xstate - how to properly handle transitions errors?
我是 Xstate 的新手,我正在努力寻找官方文档中的帮助。
问题很简单,我想知道在不应该触发的情况下是否触发了事件。
我有一个在转换方面非常严格的基本工作流程,例如,我的状态不能从 'pending' 转到 'processed' 而不从 'uploaded' 传递。
如果我使用:
stateService.send('PROCESSED')
当状态处于 'pending' 时,状态不会改变(正确)但是 Xstate 中是否有任何实用程序或事件实际上告诉我交易没有被触发,因为事件不是 allowed/correct?
这是我的状态
const stateMachine = Machine(
{
id: 'vocalTrack',
initial: 'PENDING',
context: {},
states: {
PENDING: {
on: {
UPLOADED: 'UPLOADED',
},
},
UPLOADED: {
on: {
PROCESSED: 'PROCESSED',
},
entry: 'onUploaded',
},
PROCESSED: {
on: {
READY: 'READY',
ERROR: 'ERROR',
},
exit: 'onProcessed',
},
READY: {
type: 'final',
},
ERROR: {
on: {
UPLOADED: 'UPLOADED',
},
type: 'final',
},
},
},
{
actions: {
onUploaded: (context, event) => {
console.log(`++++ onUploaded action: ++++`)
},
onProcessed: (context, event) => {
console.log(`++++ onProcessed action: ++++`)
},
},
},
)
const stateService = interpret(stateMachine)
stateService.init('PENDING')
// I'd like to catch the following workflow errors
stateService.send('UPLOADED')
stateService.send('PROCESSED')
没有任何选项可以传递给机器或解释调用,这将为您提供 "free"。不过,您可以轻松地向 "onTransition" 方法添加一些逻辑:
选项 1,在 state.changed
上验证:
service.onTransition(state => {
if (state.changed) {
console.log(`The state did change, so ${state.event.type} caused a valid transition`);
} else {
console.log(`${state.event.type} did not cause a state change`);
}
})
选项 2,根据 state.value & 事件名称进行验证:
service.onTransition(state => {
if (state.event.type === 'xstate.init'){
console.log('Init Transition');
return;
}
if(state.value === state.event.type){
console.log('Transition Valid');
}else {
console.log('Transition Invalid');
}
})
选项 1 可能是首选解决方案!您可以阅读更多相关内容 here in the documentation. The following 也与根本不存在的事件有关。
我在 React 中创建了一个小型演示应用程序来演示这一点:
这是一个已解决的问题,但我相信还有一个不同的问题,可以在机器配置级别上处理它。所以我会 post 比较一下。
考虑到:
- the machine configuration is the same as the state node config,所以它也支持
on
属性,
- if the given state does not handle the given event, it passes it to the parent,
您可以在整机配置级别定义PROCESSED
事件:
const stateMachine = Machine(
{
id: "vocalTrack",
initial: "PENDING",
context: {},
on: {
PROCESSED: {
actions: ["invalidCall"]
}
},
states: {
PENDING: {
on: {
UPLOADED: "UPLOADED"
}
},
UPLOADED: {
on: {
PROCESSED: "PROCESSED"
},
entry: "onUploaded"
},
...
},
}, {
actions: {
...
invalidCall: (context, event, meta) => {
console.log(
`invalid call of event ${event.type} on the ${meta.state.value} state`
);
}
}
}
);
实际上,在每个未处理 PROCESSED
事件的状态下,它将传播到主要配置级别。
更重要的是,wildcard descriptor exists 将捕获所有未在给定级别定义的事件,因此我们不妨捕获给定状态下不支持的所有触发事件:
on: {
"*": {
actions: ["invalidCall"]
}
},
当然,这完全取决于您的具体情况,但我喜欢该解决方案的一点是,它都停留在机器定义级别。
我还设法通过以下方式实现此功能:
export const stateMachine = createMachine({
id: 'stateMachine',
initial: 'created',
strict: true,
on: {
'*': {
cond: (_context, _event, meta) => {
throw new Error(`Cannot change from ${meta.state.value}`);
},
},
},
states: {
created: {
on: {
我是 Xstate 的新手,我正在努力寻找官方文档中的帮助。
问题很简单,我想知道在不应该触发的情况下是否触发了事件。
我有一个在转换方面非常严格的基本工作流程,例如,我的状态不能从 'pending' 转到 'processed' 而不从 'uploaded' 传递。
如果我使用:
stateService.send('PROCESSED')
当状态处于 'pending' 时,状态不会改变(正确)但是 Xstate 中是否有任何实用程序或事件实际上告诉我交易没有被触发,因为事件不是 allowed/correct?
这是我的状态
const stateMachine = Machine(
{
id: 'vocalTrack',
initial: 'PENDING',
context: {},
states: {
PENDING: {
on: {
UPLOADED: 'UPLOADED',
},
},
UPLOADED: {
on: {
PROCESSED: 'PROCESSED',
},
entry: 'onUploaded',
},
PROCESSED: {
on: {
READY: 'READY',
ERROR: 'ERROR',
},
exit: 'onProcessed',
},
READY: {
type: 'final',
},
ERROR: {
on: {
UPLOADED: 'UPLOADED',
},
type: 'final',
},
},
},
{
actions: {
onUploaded: (context, event) => {
console.log(`++++ onUploaded action: ++++`)
},
onProcessed: (context, event) => {
console.log(`++++ onProcessed action: ++++`)
},
},
},
)
const stateService = interpret(stateMachine)
stateService.init('PENDING')
// I'd like to catch the following workflow errors
stateService.send('UPLOADED')
stateService.send('PROCESSED')
没有任何选项可以传递给机器或解释调用,这将为您提供 "free"。不过,您可以轻松地向 "onTransition" 方法添加一些逻辑:
选项 1,在 state.changed
上验证:
service.onTransition(state => {
if (state.changed) {
console.log(`The state did change, so ${state.event.type} caused a valid transition`);
} else {
console.log(`${state.event.type} did not cause a state change`);
}
})
选项 2,根据 state.value & 事件名称进行验证:
service.onTransition(state => {
if (state.event.type === 'xstate.init'){
console.log('Init Transition');
return;
}
if(state.value === state.event.type){
console.log('Transition Valid');
}else {
console.log('Transition Invalid');
}
})
选项 1 可能是首选解决方案!您可以阅读更多相关内容 here in the documentation. The following
我在 React 中创建了一个小型演示应用程序来演示这一点:
这是一个已解决的问题,但我相信还有一个不同的问题,可以在机器配置级别上处理它。所以我会 post 比较一下。
考虑到:
- the machine configuration is the same as the state node config,所以它也支持
on
属性, - if the given state does not handle the given event, it passes it to the parent,
您可以在整机配置级别定义PROCESSED
事件:
const stateMachine = Machine(
{
id: "vocalTrack",
initial: "PENDING",
context: {},
on: {
PROCESSED: {
actions: ["invalidCall"]
}
},
states: {
PENDING: {
on: {
UPLOADED: "UPLOADED"
}
},
UPLOADED: {
on: {
PROCESSED: "PROCESSED"
},
entry: "onUploaded"
},
...
},
}, {
actions: {
...
invalidCall: (context, event, meta) => {
console.log(
`invalid call of event ${event.type} on the ${meta.state.value} state`
);
}
}
}
);
实际上,在每个未处理 PROCESSED
事件的状态下,它将传播到主要配置级别。
更重要的是,wildcard descriptor exists 将捕获所有未在给定级别定义的事件,因此我们不妨捕获给定状态下不支持的所有触发事件:
on: {
"*": {
actions: ["invalidCall"]
}
},
当然,这完全取决于您的具体情况,但我喜欢该解决方案的一点是,它都停留在机器定义级别。
我还设法通过以下方式实现此功能:
export const stateMachine = createMachine({
id: 'stateMachine',
initial: 'created',
strict: true,
on: {
'*': {
cond: (_context, _event, meta) => {
throw new Error(`Cannot change from ${meta.state.value}`);
},
},
},
states: {
created: {
on: {