在 xstate 中生成子机器

Posted

技术标签:

【中文标题】在 xstate 中生成子机器【英文标题】:Spawning children machines in xstate 【发布时间】:2020-02-24 21:42:29 【问题描述】:

我目前正在使用 xstate 开发一个应用程序,我有一台父计算机生成两个不同的子计算机,子计算机对不同的 API 端点进行提取,并且它们都根据情况向父计算机发送解析或拒绝事件关于 API 调用的状态,我需要有关如何确保在转换到父计算机上的空闲状态之前完成所有提取的帮助。

获取机器:

const fetchMachine: FetchMachine =(
  fetchFunction
) => (

  id: 'fetch',
  initial: States.Initialize,
  context: 
    response: null,
    error: null
  ,
  states: 
    [States.Initialize]: 
      on: 
        'FETCH.REQUEST': 
          target: States.Pending,
        
      
    ,
    [States.Pending]: 
      invoke: 
        src: 'fetch',
        onDone: 
          target: States.Success,
          actions: ['updateResponse']
        ,
        onError: 
          target: States.Failure,
          actions: ['updateError']
        
      ,
    ,
    [States.Success]: 
      entry: ['fetchSuccess'],
      on: 
        'FETCH.REQUEST': States.Pending
      
    ,
    [States.Failure]: 
      entry: ['fetchFailure'],
      on: 
        'FETCH.REQUEST': States.Pending
      
    
  

上面的机器将事件的请求发送回父级。

现在的问题是父机器并行使用这台机器,我需要帮助,以确保在转换到父机器上的空闲状态之前完成所有提取。

【问题讨论】:

【参考方案1】:

理想情况下,您会在此类情况下使用最终状态,它位于文档中的here。

我在visualizer 中重新创建了您的机器,具有并行状态,每个状态都有一个最终状态来显示它将如何转换。

为了完整起见,这里是最终机器的代码:

const parentMachine = Machine(
id: 'your_id_here',
initial: 'pending',
states: 
  pending: 
    on:  CHANGE_EVENT: 'process' 
  ,
  process: 
    type: 'parallel',
    states: 
      fetchMachine1: 
        initial: 'initialize',
        states: 
            initialize: 
                on: 
                  'FETCH.REQUEST': 
                    target: 'pending',
                  
                
              ,
              pending: 
                invoke: 
                  src: 'fetch',
                  onDone: 
                    target: 'success',
                    actions: ['updateResponse']
                  ,
                  onError: 
                    target: 'failure',
                    actions: ['updateError']
                  
                ,
              ,
              success: 
                entry: ['fetchSuccess'],
                on: 
                  'FETCH.REQUEST': 'pending'
                ,
                type: 'final' // 'success' is a final state node for 'fetchMachine1'
              ,
              failure: 
                entry: ['fetchFailure'],
                on: 
                  'FETCH.REQUEST': 'pending'
                
              
        
      ,
      fetchMachine2: 
        initial: 'initialize',
        states: 
            initialize: 
                on: 
                  'FETCH.REQUEST': 
                    target: 'pending',
                  
                
              ,
              pending: 
                invoke: 
                  src: 'fetch',
                  onDone: 
                    target: 'success',
                    actions: ['updateResponse']
                  ,
                  onError: 
                    target: 'failure',
                    actions: ['updateError']
                  
                ,
              ,
              success: 
                entry: ['fetchSuccess'],
                on: 
                  'FETCH.REQUEST': 'pending'
                ,
                type: 'final' // 'success' is a final state node for 'fetchMachine1'
              ,
              failure: 
                entry: ['fetchFailure'],
                on: 
                  'FETCH.REQUEST': 'pending'
                
              
        
      
    ,
    onDone: 'pending'
  

);

【讨论】:

所以,@TameBadger,当您在可视化器中运行它时,似乎两台机器都在监听相同的事件。例如,在fetchMachine1 上单击FETCH.REQUEST 会启动fetchMachine2。并行是这样工作的吗?这些是否需要与演员一起产生才能独立? @MikeCrowe 你也可以使用不同的事件名称,只要两者都达到最终状态,同样的逻辑适用。 这似乎没有回答 OP 的问题(或我的类似问题),因为两台 fetch 机器可以在不同的时间产生并在不同的时间完成。

以上是关于在 xstate 中生成子机器的主要内容,如果未能解决你的问题,请参考以下文章

XState.js 如何将上下文发送到机器?

如何在 XState 机器中执行操作 send('EVENT_NAME', to:'something from context')?

有没有办法在 useEffect 的反应组件中设置 xstate 机器的状态?

XState react - 跨多个组件共享机器实例

gii的使用

存储在 XSTATE 中以便跨组件访问?