• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

I Like Kill Nerds

The blog of Australian Front End / Aurelia Javascript Developer & brewing aficionado Dwayne Charrington // Aurelia.io Core Team member.

  • Home
  • Aurelia 2
  • Aurelia 1
  • About
  • Aurelia 2 Consulting/Freelance Work

Working With An API In Aurelia Store

Aurelia 1 · July 27, 2019

Unless you’re working on a completely static web application, chances are you’ll be needing to get data from an API or send data to one. In Aurelia, you would usually do this either using the HTTP Client or Fetch Client (you should be using Fetch). However, what about Aurelia Store? The versatile state management library for Aurelia.

You have two approaches you can take when using Aurelia Store with an API, and we’ll discuss the pros and cons of each one. This article is going to be a small and relatively non-technical article.

Make API requests from within your actions

Aurelia Store supports asynchronous actions, meaning you can delay their execution until the async function promise resolves. A simple Aurelia store action might look like this if using async.

async function myAction(state) {
    const newState = { ...state };

    // Do something in here

    return newState;
}

When you return from within an async function, it’s akin to a Promise.resolve the entire function itself becomes wrapped in a promise, but we’re not going to go into specifics of how async/await works in this post.

Making a function async means, you can call an API from within your action and then store the result in your state when it loads. This simplified code assumes that you’re accounting for errors in the loadUsers, hence there not being a try/catch block below.

async function myAction(state) {
    const newState = { ...state };

    newState.users = await api.loadUsers();

    return newState;
}

This approach works well because it means you can load data through actions, they are easier to debug, and you can perform transformations on the data returned. It also makes refactoring your code so much easier as you only need to change one action.

However, the downside is if the request above takes longer than expected. Maybe you’re using an Azure or Google Cloud Function (lambda function), and it takes a few seconds to start because it’s not warmed up, this request might take a few seconds to complete and meanwhile, your application slows down to a crawl. If you’re calling multiple actions, it’ll delay calling the other actions until the current one returns a state.

If you keep an eye on your actions and ensure the requests are tiny, then this should never be a problem. Adding a visual loading indicator into the application can also alleviate any loading issues. However, assumption-led decision making can sometimes backfire.

API Call First, Dispatch Action Second

In the above approach, the request and action are one function. In this approach, you request the data first and then dispatch an action after.

There is an obvious upside to this approach. Your actions execute fast; they don’t have to wait for API calls to resolve before continuing. Another upside is that it ensures your state layer and API logic remains separate. The maybe not-so-obvious downside is you now have to write and maintain two different pieces of code.

async function myAction(state, users) {
    const newState = { ...state };

    newState.users = users;

    return newState;
}

async function loadUsers() {
    const request = await fetch('/users/all');
    const response = await request.json();

    return response;
}

export class ViewModel {
    async activate() {
        const users = await loadUsers();
        dispatchify(myAction)(users);
    }
}

But, which one do I use?

The point of this post is not to tell you that you should use one over the other; it is to point out that the two approaches have upsides and downsides. Either all is fine, you only need to be aware of the caveat of async actions. When you create an asynchronous function, they all become async.

I use the second approach in my Aurelia applications. I like decoupling my state management from my API logic completely. It means if I want to remove state management at a later date or use something else, there is no tight coupling in my code. Remove my actions and call the API functions myself from my view-models (or wherever).

Dwayne

Leave a Reply Cancel reply

0 Comments
Inline Feedbacks
View all comments

Primary Sidebar

Popular

  • Testing Event Listeners In Jest (Without Using A Library)
  • How To Get The Hash of A File In Node.js
  • Waiting for an Element to Exist With JavaScript
  • Thoughts on the Flipper Zero
  • How To Get Last 4 Digits of A Credit Card Number in Javascript
  • How To Mock uuid In Jest
  • How To Paginate An Array In Javascript
  • Reliably waiting for network responses in Playwright
  • How to Copy Files Using the Copy Webpack Plugin (without copying the entire folder structure)
  • Wild Natural Deodorant Review

Recent Comments

  • Dwayne on Is Asking Developers How to Write FizzBuzz Outdated?
  • kevmeister68 on Is Asking Developers How to Write FizzBuzz Outdated?
  • Kevmeister68 on Start-Ups and Companies That Embrace Work From Anywhere Will Be More Likely to Survive the Coming Recession in 2023
  • kevmeister68 on What Would Get People Back Into the Office?
  • Dwayne on PHP Will Not Die

Copyright © 2023 · Dwayne Charrington · Log in

wpDiscuz