Ajax data request separate from state management
Published: 2023-09-11 16:53:32

---
title: Ajax data request separate from state management
published: true
description: This artcile tell you how to use FODS to separate ajax data request from state management; make same request in one page only once at the same time; react when another component submit the data to edit; and so on.
tags: 
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2023-09-11 15:51 +0000
---

## 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.

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

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

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

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:

```js
async function getPageInfo(activityConfig, userActInfo) {
  // ...
}
```

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.

```js
function useAsome() {
  const data = ref({});
  
  onMounted(() => {
    requestData().then((data) => {
      data.value = data;
    });
  });

  return data;
}
```

```js
function useBsome() {
  const data = ref({});
  
  onMounted(() => {
    requestData().then((data) => {
      data.value = data;
    });
  });

  return data;
}
```

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](https://github.com/tangshuang/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:

```js
import { source } from 'fods';

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

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

```js
import { query } from 'fods';

const data = await query(ActivityConfigDataSource);
```

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:

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

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

const someBook = await query(BookDataSource, bookId);
```

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.

```js
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);
  // ...
});
```

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).

```js
async function handleSubmit(bookId) {
  // do submit
  await renew(BookDataSource, bookId);
  // refresh UI
}
```

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](https://github.com/tangshuang/fods) and give a star.