javascriptxstate

JavaScript: xState: Connection to database implementation


I'm new to xState state machine library and am trying to implement a database connection and get data states using a third-party library. This library has a connect, disconnect functionality. It publishes 3 events, loginSuccess, loginFailureanddisconnect`. My state machine initially is in an idle state and on a button click, disconnects all existing connections and initiates a database connection attempt. When successful, it goes into getting data state. Below is my state machine:

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');
});

Any help is appreciated.


Solution

  • THe event object has data property that can be set. To pass data, I do the following:

    buttonClickService.send('LOGIN_FAILURE', { data: errorMessage })