Response Handling in ESW-TS

This section helps to understand how responses have been modeled in TMT architecture and, also how they can be handled at UI application side.

If you have not gone the Services Section, we recommend you to check Services out first. Assuming you have read through the Services section and what all types of response can be returned by the Service of your current interest.

The Response types are Union types/ADT’s. All of them are tagged by _type field, this field provides information at compile time to developers of all possible response variation at runtime for the current response.

Typescript
source// response handlers
const onCancelled = () => {
  // do something on receiving Cancelled type
}
const onCompleted = () => {
  // do something on receiving Completed type
}
const onStarted = () => {
  // do something on receiving Started type
}
const onError = () => {
  // do something on receiving Error type
}
const onInvalid = () => {
  // do something on receiving Invalid type
}
const onLocked = () => {
  // do something on receiving Locked type
}

const prefix = new Prefix('ESW', 'component_1')
const componentId = new ComponentId(prefix, 'Assembly')
const commandService: CommandService = await CommandService(componentId, {
  tokenFactory
})

const setup = new Setup(prefix, 'move', [])
const submitResponse: SubmitResponse = await commandService.submit(setup)

// Handle all variations (Exhaustive switch pattern)
switch (submitResponse._type) {
  case 'Cancelled':
    onCancelled()
    break
  case 'Completed':
    onCompleted()
    break
  case 'Started':
    onStarted()
    break
  case 'Error':
    onError()
    break
  case 'Invalid':
    onInvalid()
    break
  case 'Locked':
    onLocked()
    break
}

// or handle few types

switch (submitResponse._type) {
  case 'Completed':
    onCompleted()
    break
  case 'Started':
    onStarted()
    break
  case 'Error':
    onError()
    break
  default: // !!important!!
  // do something by default for other cases
}
Normal response

All non-ADT or Normal response types (for ex: Done, LogMetadata, etc.) does not require extra effort of handling it with switch cases. Those models do not have any discriminatory field like _type and there will always be one variation, and the information about all fields inside model will be statically known.

Asynchronous Programming

You may have notice that we have used async-await syntax in all examples provided in the different pages of this documentation. However, one may still want to write using combinators provided by Promise, since most of the ESW-TS service methods are Promise based.

Promise is provided by Javascript language,Using which we can write asynchronous programs in a more manageable way. Using Async/Await syntax, a promise-based asynchronous code can be written in a synchronous format which saves a lot of time and code becomes scalable. We recommend using async-await syntax for writing asynchronous code as it increases readability of the code. When using callbacks or combinators on top of Promise, issues like callback hell emerges over time.

For instance, following example showcases two scenarios without async-await syntax and how it would look like

  1. Sending submit commands using CommandService in sequence
  2. Sending submit commands using CommandService in parallel
Typescript
source
const prefix = new Prefix('ESW', 'component_1') const componentId = new ComponentId(prefix, 'HCD') CommandService(componentId) .then((commandService) => { const setup1 = new Setup(prefix, 'move', []) const setup2 = new Setup(prefix, 'rotate', []) const setup3 = new Setup(prefix, 'set', []) const responsePromise = commandService.submit(setup1) //sequential way to handle multiple submit calls responsePromise .then((submitResponse1) => { handleResponse(submitResponse1) commandService.submit(setup2).then((submitResponse2) => { handleResponse(submitResponse2) commandService.query(submitResponse2.runId).then(fetchNewESWState) }) }) .catch(handleError) // parallel way to handle multiple promises const responsePromise3 = commandService.submit(setup3) Promise.all([responsePromise, responsePromise3]).then((submitResponses) => { submitResponses.forEach(handleResponse) const lastResponse = submitResponses.pop() if (lastResponse) { commandService.query(lastResponse.runId).then(fetchNewESWState) } }) }) .catch((err) => { handleError(err) }) const handleError = (error: Error) => { // See Error handling section for in general details throw new Error(error.message) } const handleResponse = (response: SubmitResponse) => { // See Response handling section for in general details console.log(response) } const fetchNewESWState = () => { // fetch new state from backend }

The following example showcases the same above scenarios with async-await syntax.

  1. Sending multiple submit commands with async-await syntax
Typescript
source
const handleError = (error: Error) => { // See Error handling section for details throw new Error(error.message) } const handleResponse = (response: SubmitResponse) => { // See Response handling section for more details console.log(response) } const prefix = new Prefix('ESW', 'component_1') const componentId = new ComponentId(prefix, 'HCD') try { const commandService = await CommandService(componentId) const setup1 = new Setup(prefix, 'move', []) const setup2 = new Setup(prefix, 'rotate', []) const setup3 = new Setup(prefix, 'set', []) //sequential way to handle multiple submit calls await commandService.submit(setup1) const responsePromise2 = await commandService.submit(setup2) const queryResponse = await commandService.query(responsePromise2.runId) handleResponse(queryResponse) // parallel way to handle multiple promises const responsePromise3 = commandService.submit(setup3) const responsePromise4 = commandService.submit(setup1) const submitResponses = await Promise.all([responsePromise3, responsePromise4]) submitResponses.forEach(handleResponse) const lastResponse = submitResponses.pop() if (lastResponse) { const queryRes = commandService.query(lastResponse.runId) } } catch (err) { handleError(err as Error) }
async-await

We strongly recommend to use async-await while writing asynchronous code in Javascript.