How to customize alova's request adapter
Tags: vue, react, alova, axios
Published: 2023-11-23 09:46:51

alova is a lightweight request strategy library designed to simplify the management and use of interfaces. By simply configuring parameters, you can implement complex requests such as sharing requests, paging requests, form submissions, breakpoint resumption, etc., without writing a lot of code, improving development efficiency, application performance, and reducing server pressure.

When using alova to send network requests, we often need to add some information to the request header, such as authentication tokens, public parameters, etc. alova provides two ways to configure request headers at global and individual request granularities. The method of adding request headers is very similar to axios.

## Get to know the request adapter

Remember how to create an Alova instance?

```javascript
const alovaInstance = createAlova({
   // ...
   requestAdapter: GlobalFetch()
});
```

Yes, `requestAdapter` is a request adapter. Internal request sending and receiving will rely on the request adapter. `GlobalFetch` manages requests through the fetch api. In most cases we can use it, but when` When alova` is running in an environment where the fetch api is not available (such as app, applet), you need to replace a request adapter that supports the current environment.

##Write an own request adapter

So how to customize a request adapter? Very simple, it is actually a function. This function will be called every time a request is made, and an object will be returned. This object contains items such as `url`, `method`, `data`, `headers`, `timeout`, etc. Request related data collections. Although there are many fields, we only need to access the data we need.

### Request adapter structure

The request adapter will receive the request-related parameters and the method instance currently being requested, and return a collection of response-related functions.

```javascript
function CustomRequestAdapter(requestElements, methodInstance) {
   // send request...
   return {
     async response() {
       // ...return response data
     },
     async headers() {
       // Asynchronous function that returns response headers
     },
     abort() {
       //Interrupt request, this function will be triggered when abort is called externally
     },
     onDownload(updateDownloadProgress) {
       //Download progress information, updateDownloadProgress is continuously called internally to update the download progress.
     },
     onUpload(updateUploadProgress) {
       //Upload progress information, updateUploadProgress is continuously called internally to update the upload progress.
     }
   };
}
```

#### Request parameter details

**requestElements**

Relevant elements of the send request, including the following data.

```typescript
interface RequestElements {
   //Request url, get parameters are included in it
   readonly url: string;

   // Request type, such as GET, POST, PUT, etc.
   readonly type: MethodType;

   //Request header information, object
   readonly headers: Arg;

   //Request body information
   readonly data?: RequestBody;
}
```

**methodInstance**

The method instance of the current request

#### Return parameter details

**response (required)**

An asynchronous function that returns the response value, which will be passed to the global response interceptor (responded);

**headers (required)**

An asynchronous function, the response header object returned by the function will be passed to the transformData conversion hook function of the Method instance;

**abort (required)**

A common function, which is used for interrupt requests. When the `abort` function is called in the [Manual Interrupt Request](#Manual Interrupt Request) chapter, the function that actually triggers the interrupt request is this interrupt function;

**onDownload(optional)**

A normal function that receives a callback function that updates the download progress. Customize the frequency of progress updates within this function. In this example, it simulates an update every 100 milliseconds. The `updateDownloadProgress` callback function receives two parameters, the first parameter is the total size, and the second parameter is the downloaded size;

**onUpload(optional)**

A normal function that receives a callback function that updates the upload progress. Customize the frequency of progress updates within this function. In this example, it simulates an update every 100 milliseconds. The `updateUploadProgress` callback function receives two parameters, the first parameter is the total size, and the second parameter is the uploaded size;

## (Case) XMLHttpRequest request adapter

The following is an example of an adapter that sends requests through XMLHttpRequest. It is mainly used to demonstrate how to write the adapter. The code is incomplete and cannot be run.

```javascript
function XMLHttpRequestAdapter(requestElements, methodInstance) {
   // Deconstruct the data needed
   const { url, type, data, headers } = config;

   // send request
   const xhr = new XMLHttpRequest();
   xhr.open(type, url);
   for (const key in headers) {
     xhr.setRequestHeader(key, headers[key]);
   }
   const responsePromise = new Promise((resolve, reject) => {
     xhr.addEventListener('load', event => {
       // Process response data
       resolve(/* ... */);
     });
     xhr.addEventListener('error', event => {
       // Handle request errors
       reject(/* ... */);
     });
   });

   xhr.send(JSON.stringify(data));

   return {
     // Asynchronous function that returns response data
     response: () => responsePromise,

     // Asynchronous function that returns response headers
     headers: () => responsePromise.then(() => xhr.getAllResponseHeaders()),
     abort: () => {
       xhr.abort();
     },

     //Download progress information, updateDownloadProgress is continuously called internally to update the download progress.
     onDownload: updateDownloadProgress => {
       xhr.addEventListener('progress', event => {
         //Data receiving progress
         updateDownloadProgress(event.total, event.loaded);
       });
     },

     //Upload progress information, updateUploadProgress is continuously called internally to update the upload progress.
     onUpload: updateUploadProgress => {
       xhr.upload.onprogress = event => {
         updateUploadProgress(event.total, event.loaded);
       };
     }
   };
}
```


> Complete XMLHttpRequest request adapter code [click here to view the source code](https://github.com/alovajs/adapter-xhr/blob/main/src/requestAdapter.ts).

## End

The above is how to write alova's custom request adapter, which can flexibly handle different request header setting requirements.

If you have any usage questions, you can join the following group chat for consultation, or you can publish Discussions in [github repository](https://github.com/alovajs/alova/discussions). If you encounter problems, please also post in [github's issues](https://github.com/alovajs/alova/issues), we will solve it as soon as possible.

- [Join the Discord community to participate in communication](https://discord.gg/S47QGJgkVb)

You are also welcome to contribute, please go to [Contribution Guide](https://alova.js.org/contributing/overview).

> The following is a tutorial for some chapters. If you want to learn more about the usage of alovajs, please come to [alova official website](https://alova.js.org/) to learn.