基于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
相关产品推荐
相关产品推荐

