DEV Community

frustigor
frustigor

Posted on

Ajax data request separate from state management

Problems

You may have the experience about ajax request inside a state management code. In many cases, we have to be very careful about the ajax request because state lifecycle may cause several times request. And the data we want to use may from same source, but not easy to manage.

Let's review some examples.

async function getActivityConfig() {
  // ...
}

async function getUserActInfo() {
  const activityConfig = await getActivityConfig();
  // ...
}

async function getPageInfo() {
  const activityConfig = await getActivityConfig();
  const userActInfo = await getUserActInfo();
  // ...
}
Enter fullscreen mode Exit fullscreen mode

In the previous code, I want to show a cause in which we have to request getActivityConfig twice. To avoid request twice, we may change the code to:

async function getPageInfo(activityConfig, userActInfo) {
  // ...
}
Enter fullscreen mode Exit fullscreen mode

However, after this change, we have to invoke all the functions outside the module.

In this situation, we may be boring about data request arrangement. Is there a way to ignore the twice requesting? Yes!!

Any way, let's look into another example.

function useAsome() {
  const data = ref({});

  onMounted(() => {
    requestData().then((data) => {
      data.value = data;
    });
  });

  return data;
}
Enter fullscreen mode Exit fullscreen mode
function useBsome() {
  const data = ref({});

  onMounted(() => {
    requestData().then((data) => {
      data.value = data;
    });
  });

  return data;
}
Enter fullscreen mode Exit fullscreen mode

In the previous code, we define two composition api function to provide data for some components. However, the two functions are written by different people, they are not care about the ajax requesting duplicate. When the two function are used in different components, ajax requesting are sent more than once.

Is there a way to avoid this knowlege isolate amoung different developers even though teams? Yes!!

Data Source

Now, let's take a glance of FODS which is a small library to resolve data management problems.

In FODS, there is one core concept source. A source is a data request defination like a normal async function:

import { source } from 'fods';

const ActivityConfigDataSource = source(async () => {
  // ...
});
Enter fullscreen mode Exit fullscreen mode

The source object contains the data source about activity config, and will feed the frontend codes data.

import { query } from 'fods';

const data = await query(ActivityConfigDataSource);
Enter fullscreen mode Exit fullscreen mode

A data source can be query any times, the result will be the same until renew.

Yes, the underlying principle is CACHE. We save the data from data source in a memory cache and spit out it when be query.

The difference between source and cache is concept, a source stands for data and the way get data. A source may maintain different data by different params, for exmaple:

const BookDataSource = source((bookId) => {
  // ...
});

// ------------------

const someBook = await query(BookDataSource, bookId);
Enter fullscreen mode Exit fullscreen mode

The output data is based on the given params. There is a store/depository inside a source object which maintain each params' data.

This is the way of FODS to manage data requests.

Now, we can use FODS to resolve our problems which mentioned at the begining of this article.

const ActivityConfigSource = source(async () => {
  // ...
});

const UserActInfoSource = source(async () => {
  const activityConfig = await query(ActivityConfigSource);
  // ...
});

const PageInfoSource = source(async () => {
  const activityConfig = await query(ActivityConfigSource);
  const userActInfo = await query(UserActInfoSource);
  // ...
});
Enter fullscreen mode Exit fullscreen mode

When we want a data, we alway get it from a data source. And the same ajax request will never be sent after the first request is sent.

Renew Source

However, we may submit data from a form and the UI should be updated after new data comes. At this time, we need to renew the data source (re-pull data from http api).

async function handleSubmit(bookId) {
  // do submit
  await renew(BookDataSource, bookId);
  // refresh UI
}
Enter fullscreen mode Exit fullscreen mode

In the previous code, we can renew to let the source use new data, and after flushing we will get new data when invoke query again, at this time, the UI will use new data to render.

Abstraction

FODS open a small window for our frontend developers to think about abstraction of frontend data layer. In our development experience, we always think how to arrange state, and treat ajax requests as some effects and do ajax in onMounted. However, may be, there is a perfect architecture which treat ajax requests as isolated operation disengage from UI programming.

In a frontend javascript application, data source is from database to ODS to BFF to browser/SSR, in fact, data is changing much less then state. A book's info data may not change for years, a student's info may not change for 3-5 years, even a shop order's data may not change during 10 minutes. The thing we need to do is renew it after it changed.

To renew a data may not must be done in a handler, it may be done by a websocket or any other way. If we split data ajax request out in our UI programming, it may be more comfortable for us to management state.

Summary

This article give you a glance of FODS to resolve duplicate ajax request problems. Any way, in FODS, there are more usages such as action stream and event listener. If you are interested in it, you can watch the github repo and give a star.

Top comments (0)