🗡️
ConanJs
  • What is ConanJs?
  • Why ConanJs...
    • ... if coming from Redux
    • ... if using vanilla React
    • ... if learning React
    • ... if not using React
  • How to install/use ConanJs
  • About us / Github / Contact us
  • Demos
    • Demo Gallery
    • Conan State Demos
      • Hello World
      • Todos
        • Todos - Basic
        • Todos - Async
        • Todos - Optimistic
      • Github issues viewer
    • Conan Flow Demos
      • Authentication
  • CONAN DATA
    • General Concepts
    • Conan State
      • Actions & Reducers
        • Reducers
        • Actions
      • Creating State
      • Observing State
        • Live rendering
        • Connecting
      • Composing State
      • Scaling State
      • Orchestrating State
      • Life cycle
        • Async handling
        • Introspection
      • Testing state
    • Conan Flow
      • Creating Flows
      • Serialising Flows
      • Observing Flows
  • CONAN Runtime
  • Dependency Injection
    • General Concepts
    • Creating the Context
    • Using the Context
  • ASAPs
  • Logging
  • API
    • Main Classes
      • Conan
        • StateDef
      • ConanState
      • ConanFlow
        • UserFlowDef
        • UserStatusDef
        • Status
    • Conan State Classes
      • Thread
      • ConnectedState
      • MonitorInfo
      • MetaInfo
    • Dependency Injection
      • DiContextFactory
    • ASAPS
      • Asaps
      • Asap
Powered by GitBook
On this page
  • Introduction
  • Async Actions
  • Monitor actions
  • Auto-bind
  • The Monitor Thread
  • Example

Was this helpful?

  1. CONAN DATA
  2. Conan State
  3. Life cycle

Async handling

PreviousLife cycleNextIntrospection

Last updated 4 years ago

Was this helpful?

Introduction

ConanJs gives you a few mechanisms to announce within your actions that you are performing asynchronous operations.

These are the benefits:

  • NO boiler plate code to update your state asynchronously.

  • Automatically updates the to reflect all the async operations running and their details. Allowing you to subscribe to these updates, to easily add loading screens, block buttons etc.

Check our for an example without boiler plate code and which displays the status of the async operations

  • Allows accessing the underlying running at the moment. Note this combined with the ASAPs being cancellable, makes complex scenarios like optimistic updates much simpler

Check our for an example with optimistic updates

Async Actions

There are two mechanisms to declare async actions: auto-bind and monitor actions.

Monitor actions

, you can access the monitor from the provided thread and the framework will update the all the way through the life cycle of the ASAP

return thread.monitor(
    //An Asap
    diContext.issuesService.fetch(repo, org, page).catch(() => thread.reducers.$fetch([])),
    //What to do when the asap resolves
    (issues, reducers) => reducers.$fetch(issues as Issue[]),
    //Next two params are for logging purposes
    // - Description of the async operation
    'fetch',
    // - Payload (also shown on the logging)
    [repo, org, page]
)

Auto-bind

Auto-bind works based on naming convention, it basically builds a monitor automatically for a given reducer given a method that returns an ASAP.

The requirements for autoBind are.

  • The reducer and the action to auto-bind should have matching names (reducer prefixed with a $, action without it)

  • They reducer must take only one parameter.

  • The action to autobind needs to return an ASAP of the same type as the type from reducer parameter.

If all these requirements are met, the action you passed through the autobind will be now accessible as an action for the ConanState and, if you invoke it, in addition to returning the ASAP it will monitor it and invoke the associated reducer.

This is better seen with an example

function updateToAsync (): ASAP<number>{ 
    //This could be any ASAP, in this case we use a dummy delay
    return Asaps.delay (3, 1000);
}

const autoBoundCounter$ = Conan.state ({
    name: 'autoBoundCounter',
    reducers: getState => ({
        $updateTo (newValue) {
            return newValue
        }
    }),
    autoBind: {
        updateTo: updateToAsync
    }
})

// This will update to 5 in 1s
autoBoundCounter$.do.updateTo (5)

The Monitor Thread

The monitor thread contains the updates to the Monitor Info caused by changes in async actions.

{
    inProgressActions: [],
    status: MonitorStatus.IDLE, //'IDLE'
}

This state is reached as soon as you start the Conan State, or as soon as all the async actions running are fulfilled.

There are three properties in the monitorInfo

  • currentAction: This will be populated if there is at least one async action running at the moment, this will contain the representation of the async action that is right now causing an update in the Monitor Thread.

  • status: One of the following

export enum MonitorStatus {
    IDLE = 'IDLE',
    ASYNC_START = "ASYNC_START",
    ASYNC_FULFILLED = "ASYNC_FULFILLED",
    ASYNC_CANCELLED = "ASYNC_CANCELLED",
}
  • inProgressActions: All the actions running at the time that this currentAction is being updated.

Example

A new monitor actions is triggered with name 'updateAsync' and its payload is '5' the Monitor Info would update immediately to:

{
    inProgressActions: [{
        name: 'updateAsync',
        payload: 5,
        asap: [theAsap]
    }],
    currentAction: {
        name: 'updateAsync',
        payload: 5,
        asap: [theAsap]
    },
    status: MonitorStatus.ASYNC_START, //'"ASYNC_START"'
}

If another action is triggered, with the same name, but with a payload of '3', the monitor info would look like:

{
    inProgressActions: [{
        name: 'updateAsync',
        payload: 5,
        asap: [theAsap]
    },{
        name: 'updateAsync',
        payload: 3,
        asap: [theAsap]
    }],
    currentAction: {
        name: 'updateAsync',
        payload: 3,
        asap: [theAsap]
    },
    status: MonitorStatus.ASYNC_START, //'"ASYNC_START"'
}

If the action with payload 3 is resolved successfully:

{
    inProgressActions: [{
        name: 'updateAsync',
        payload: 5,
        asap: [theAsap]
    }],
    currentAction: {
        name: 'updateAsync',
        payload: 3,
        asap: [theAsap]
    },
    status: MonitorStatus.ASYNC_FULFILLED, //'ASYNC_FULFILLED'
}

Then, if the action with payload 5 is resolved, since is the last one, the Monitor Info will update twice.

Once so that we know that the async action has been fulfilled

{
    inProgressActions: [{
        name: 'updateAsync',
        payload: 5,
        asap: [theAsap]
    }],
    currentAction: {
        name: 'updateAsync',
        payload: 5,
        asap: [theAsap]
    },
    status: MonitorStatus.ASYNC_FULFILLED, //'ASYNC_FULFILLED'
}

Once more to let us know that no more async actions are running at the moment

{
    inProgressActions: [],
    status: MonitorStatus.IDLE, //'IDLE'
}

Check our example to see a monitor example.

You can also see this using a service in this example

The value of the when there are no async actions running is:

Github
Todos - Async
Monitor Info
Todos - Async
ASAPs
Todos - Optimistic
When you describe your actions
Monitor Thread
Monitor Async thread