You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于xState实现数据库连接状态机的事件参数传递问题求助

问题:XState状态机中如何传递loginFailure的错误消息并捕获

我是XState状态机库的新手,正尝试使用第三方库实现数据库连接与数据获取状态机。该库具备connect、disconnect功能,会发布loginSuccess、loginFailure、disconnect三种事件。我的状态机初始处于idle状态,点击按钮时会断开所有现有连接并发起数据库连接尝试,连接成功后进入数据获取状态。以下是我的状态机代码:

const buttonClickMachine = createMachine({
  id: 'GetTransactionButtonClick',
  initial: 'idle',
  context: {
    returnCode: undefined,
    waitTimeInMilliSeconds: _waitTimeInMilliSeconds,
    arg1: arg1,
    arg2: arg2,
    arg3: arg3,
    errorMessage: undefined
  },

  states: {
    idle: {
      on: {
        BUTTON_CLICK: {
          target: 'disconnectingDB'
        }
      }
    },
    disconnectingDB: {
      invoke: {
        src: (context, event) => disconnectDB(context.waitTimeInMilliSeconds),
        onDone: {
          target: 'waitingForDBConnection',
          actions: assign({
            returnCode: (context, event) => event.data
          })
        },
        onError: {
          target: 'showingAlert',
          actions: assign({
            errorMessage: (context, event) => event.data
          })
        }
      }
    },
    
    gettingTransactions: {
      invoke: {
        src: (context, event) => getTransactions(),
        onDone: {
          target: 'success',
          actions: assign({
            returnCode: (context, event) => event.data
          })
        },
        onError: {
          target: 'showingAlert',
          actions: assign({
            errorMessage: (context, event) => event.data
          })
        },
        on: {
           REJECT: 'showingDisconnectAlert'
        }
      }
    },

    waitingForDBConnection: {
      invoke: {
        src: (context, event) => connectDB(context.waitTimeInMilliSeconds, context.arg1, context.arg2, context.arg3),
        on: {
           LOGIN_SUCCESS: 'gettingTransactions',
           LOGIN_FAILURE: {
                  target: 'showingAlert',
                  actions: assign({
                            errorMessage: (context, event) => event.data
          })
         }
        },

        onError: {
          target: 'showingAlert',
          actions: assign({
            errorMessage: (context, event) => event.data
          })
        },
        on: {
           REJECT: 'showingDisconnectAlert'
        }
      }
    },

    showingAlert: {
      invoke: {
        src: (context, event) => showAlert(context.errorMessage),
        onDone: {
          target: 'idle'
        }
      }
    },

    success: {
      type: 'final'
    }
  }
});
const _connectionObject = ConnectionObject.initialize();
const buttonClickService = interpret(buttonClickMachine).start();

function connectDB(waitTimeInMilliSeconds: any, arg1: any, arg2: any, arg3: any) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      try {
        connect(Number(arg1), Number(arg2), Number(arg3));
        
        });

      } catch (error) {
        reject('[ErrorCode:-98] Unable to connect to database server. Please try again');
      }
    }, Number(waitTimeInMilliSeconds));
  });
}
_connectionObject.on('loginSuccess', function() {
          buttonClickService.send('LOGIN_SUCCESS');
        });
        _connectionObject.on('loginFailure', function(errorMessage) {
            
           buttonClickService.send('LOGIN_FAILURE', //how do I send the errorMessage as a parameter that I can capture in my connectionToDB state);

          });
_connectionObject.on('disconnect', function() {
  console.log('disconnect to db');
    buttonClickService.send('REJECT');
});

目前我遇到的问题是:在loginFailure事件回调中,如何将errorMessage作为参数传递给状态机的waitingForDBConnection状态并捕获?


解决方案

1. 发送事件时携带错误数据

在loginFailure的回调中,给send方法传递第二个参数作为事件的data字段:

_connectionObject.on('loginFailure', function(errorMessage) {
  buttonClickService.send({
    type: 'LOGIN_FAILURE',
    data: errorMessage // 将错误消息挂载到事件的data属性上
  });
});

2. 在状态机中接收并处理事件数据

你的状态机中已经配置了assign动作来更新errorMessage,只需确保从事件的data字段取值即可(当前代码逻辑已正确,只需保证事件携带对应数据):

LOGIN_FAILURE: {
  target: 'showingAlert',
  actions: assign({
    errorMessage: (context, event) => event.data // 直接获取传递的错误消息
  })
}

3. 额外优化:修正重复的on配置

注意waitingForDBConnection状态的invoke配置里存在两个重复的on属性,会导致后者覆盖前者,需要合并为一个:

waitingForDBConnection: {
  invoke: {
    src: (context, event) => connectDB(context.waitTimeInMilliSeconds, context.arg1, context.arg2, context.arg3),
    on: {
       LOGIN_SUCCESS: 'gettingTransactions',
       LOGIN_FAILURE: {
              target: 'showingAlert',
              actions: assign({
                        errorMessage: (context, event) => event.data
              })
       },
       REJECT: 'showingDisconnectAlert' // 合并REJECT事件到同一个on对象中
    },
    onError: {
      target: 'showingAlert',
      actions: assign({
        errorMessage: (context, event) => event.data
      })
    }
  }
},

完成以上步骤后,第三方库的loginFailure错误消息就能成功传递到状态机中,更新到context的errorMessage字段,后续showingAlert状态即可直接使用该错误消息。


内容的提问来源于stack exchange,提问作者SoftwareDveloper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 20:10:26