forked from mengyxu/noob-components
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
296 lines
6.9 KiB
296 lines
6.9 KiB
|
3 months ago
|
# Axios3 (Third HTTP Client Variant)
|
||
|
|
|
||
|
|
> Latest HTTP client with AxiosOptions interface and flexible response filtering.
|
||
|
|
|
||
|
|
## File
|
||
|
|
|
||
|
|
`plugs/http/axios3.ts`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
Third and most refined iteration. Introduces `AxiosOptions` interface for flexible request options and `filter` callback for custom response processing.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Key Improvements over Axios2
|
||
|
|
|
||
|
|
| Feature | Axios2 | Axios3 |
|
||
|
|
|---------|--------|--------|
|
||
|
|
| Options interface | `noMsg?, noLoading?` as positional | `AxiosOptions` object |
|
||
|
|
| Response filter | Built-in only | Customizable via `filter` option |
|
||
|
|
| Query params merging | Simple params | `mergeQueryParams()` |
|
||
|
|
| Success detection | `response.success` only | Multiple indicators |
|
||
|
|
| URLSearchParams support | No | Yes |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## AxiosOptions Interface
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export interface AxiosOptions {
|
||
|
|
noMsg?: boolean | null;
|
||
|
|
noLoading?: boolean | null;
|
||
|
|
filter?: (response) => any;
|
||
|
|
query?: QueryParams;
|
||
|
|
}
|
||
|
|
|
||
|
|
type QueryParams = URLSearchParams | Record<string, any> | ConstructorParameters<typeof URLSearchParams>[0];
|
||
|
|
```
|
||
|
|
|
||
|
|
### Options Properties
|
||
|
|
|
||
|
|
| Property | Type | Purpose |
|
||
|
|
|----------|------|---------|
|
||
|
|
| `noMsg` | `boolean \| null` | Suppress success/error messages |
|
||
|
|
| `noLoading` | `boolean \| null` | Suppress loading indicator |
|
||
|
|
| `filter` | `(response) => any` | Custom response transformation |
|
||
|
|
| `query` | `QueryParams` | Additional query parameters to merge |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Axios Instance Configuration
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const config = {
|
||
|
|
baseURL: process.env.VUE_APP_BASE_URL ? "/api" : "",
|
||
|
|
timeout: 60 * 1000,
|
||
|
|
withCredentials: true,
|
||
|
|
};
|
||
|
|
|
||
|
|
const _axios = axios.create(config);
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Registration Functions
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export const registerBaseUrl = (url) => {
|
||
|
|
_axios.defaults.baseURL = url;
|
||
|
|
};
|
||
|
|
|
||
|
|
export const registerRouter = (routerP) => {
|
||
|
|
router = routerP;
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Request Interceptor
|
||
|
|
|
||
|
|
Located at `plugs/http/axios3.ts` lines 29-48:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
_axios.interceptors.request.use(
|
||
|
|
function (config) {
|
||
|
|
const time = new Date().getTime().toString();
|
||
|
|
const params = new URLSearchParams(config.params);
|
||
|
|
if (params.toString()) {
|
||
|
|
delEmpty(params);
|
||
|
|
params.append("t", time);
|
||
|
|
config.params = params;
|
||
|
|
}
|
||
|
|
const data = config.data;
|
||
|
|
if (data != null && typeof data === "object") {
|
||
|
|
delEmpty(data);
|
||
|
|
data.t = time;
|
||
|
|
}
|
||
|
|
return config;
|
||
|
|
},
|
||
|
|
function (error) {
|
||
|
|
return Promise.reject(error);
|
||
|
|
}
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
### Key Difference
|
||
|
|
|
||
|
|
Uses `URLSearchParams` for params manipulation, ensuring proper encoding.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## delEmpty Function (Enhanced)
|
||
|
|
|
||
|
|
Located at `plugs/http/axios3.ts` lines 50-65:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
function delEmpty(data) {
|
||
|
|
if (data && data instanceof URLSearchParams) {
|
||
|
|
for (const [k, v] of data.entries()) {
|
||
|
|
if (!v) data.delete(k);
|
||
|
|
}
|
||
|
|
} else if (data && typeof data === "object") {
|
||
|
|
for (const item in data) {
|
||
|
|
if (data.hasOwnProperty(item)) {
|
||
|
|
const val = data[item];
|
||
|
|
if ((val == null || val == "null" || val == "") && val !== 0 && val !== false) {
|
||
|
|
delete data[item];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Enhanced Behavior
|
||
|
|
|
||
|
|
- Handles `URLSearchParams` natively
|
||
|
|
- Also deletes empty strings for `false` values
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Default Response Filter
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const defaultFilterResp = (resp) => {
|
||
|
|
const isSuccess = resp.success || resp.status === "ok" || resp.status === "success" || resp.data != null;
|
||
|
|
const isError = resp.success === false || resp.status === "error";
|
||
|
|
if (isSuccess) {
|
||
|
|
return resp.data ? resp.data : resp;
|
||
|
|
} else if (isError) {
|
||
|
|
return false;
|
||
|
|
} else return resp;
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
### Success Detection Logic
|
||
|
|
|
||
|
|
Accepts any of these as success:
|
||
|
|
- `response.success === true`
|
||
|
|
- `response.status === "ok"`
|
||
|
|
- `response.status === "success"`
|
||
|
|
- `response.data != null`
|
||
|
|
|
||
|
|
Returns `response.data` on success, `false` on error, raw response otherwise.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Query Params Merging
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
function mergeQueryParams(...params: Array<QueryParams>) {
|
||
|
|
const res: URLSearchParams = new URLSearchParams();
|
||
|
|
for (const param of params) {
|
||
|
|
if (param == null) continue;
|
||
|
|
let parsed;
|
||
|
|
if (param instanceof URLSearchParams) {
|
||
|
|
parsed = param;
|
||
|
|
} else {
|
||
|
|
parsed = new URLSearchParams(param);
|
||
|
|
}
|
||
|
|
|
||
|
|
parsed
|
||
|
|
.entries()
|
||
|
|
.filter(([k, v]) => v != null && v != "null" && v != "undefined" && v != "")
|
||
|
|
.forEach(([k, v]) => res?.append(k, v));
|
||
|
|
}
|
||
|
|
|
||
|
|
return res ?? new URLSearchParams();
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Features
|
||
|
|
|
||
|
|
- Merges multiple query param sources
|
||
|
|
- Filters out `null`, `"null"`, `"undefined"`, and empty strings
|
||
|
|
- Supports both `URLSearchParams` and plain objects
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Export Methods with AxiosOptions
|
||
|
|
|
||
|
|
| Method | Signature | Purpose |
|
||
|
|
|--------|-----------|---------|
|
||
|
|
| `post` | `(url, data?, options?: AxiosOptions)` | POST request |
|
||
|
|
| `get` | `(url, data?: QueryParams, options?: AxiosOptions)` | GET request |
|
||
|
|
| `put` | `(url, data?, options?: AxiosOptions)` | PUT request |
|
||
|
|
| `delate` | `(url, data?, options?: AxiosOptions)` | DELETE request |
|
||
|
|
| `upload` | `(file, url, data)` | File upload |
|
||
|
|
| `getFile` | `(url, data?, options?: AxiosOptions)` | Download as blob |
|
||
|
|
| `download` | `(fileName, url, data, callBack?)` | Browser download |
|
||
|
|
| `registerBaseUrl` | `(url)` | Set base URL |
|
||
|
|
| `registerRouter` | `(routerP)` | Set router |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Response Handler with Filter
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
function handResponse(response, resolve, options: AxiosOptions = {}) {
|
||
|
|
if (!options.noLoading) {
|
||
|
|
close();
|
||
|
|
}
|
||
|
|
|
||
|
|
const filterResponse = options.filter ?? defaultFilterResp;
|
||
|
|
const result = filterResponse(response);
|
||
|
|
|
||
|
|
if (result) {
|
||
|
|
if (!options.noMsg && response.message) {
|
||
|
|
showMessage("success", response.message);
|
||
|
|
}
|
||
|
|
resolve(result);
|
||
|
|
} else {
|
||
|
|
// Error handling with router redirect
|
||
|
|
if (response.message == "session timeout") {
|
||
|
|
router?.push("/login");
|
||
|
|
response.message = t("http.unLogin");
|
||
|
|
}
|
||
|
|
if (response.message == "no permission") {
|
||
|
|
response.message = t("http.unPermission");
|
||
|
|
}
|
||
|
|
if (response.message?.indexOf("no permission for ") == 0) {
|
||
|
|
response.message = t("http.noPermission");
|
||
|
|
}
|
||
|
|
if (!options.noMsg && response.message) {
|
||
|
|
showMessage("error", response.message);
|
||
|
|
}
|
||
|
|
response.error && console.log(response.error);
|
||
|
|
resolve(false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Usage Examples
|
||
|
|
|
||
|
|
### Basic GET with options
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { Axios3 } from '@/plugs/http';
|
||
|
|
|
||
|
|
const data = await Axios3.get('/api/users', { page: 1 }, { noLoading: true });
|
||
|
|
```
|
||
|
|
|
||
|
|
### GET with query merging
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const data = await Axios3.get('/api/search', { keyword: 'test' }, {
|
||
|
|
query: { sort: 'name' }
|
||
|
|
});
|
||
|
|
// Results in: /api/search?keyword=test&sort=name
|
||
|
|
```
|
||
|
|
|
||
|
|
### Custom filter
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const result = await Axios3.post('/api/custom', data, {
|
||
|
|
filter: (response) => {
|
||
|
|
if (response.code === 200) {
|
||
|
|
return response.result;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Anti-Patterns
|
||
|
|
|
||
|
|
1. **`delate` function name** - Should be `delete`
|
||
|
|
2. **Resolves `false` for errors** - Inconsistent with promise conventions
|
||
|
|
3. **`noMsg` not passed to error handler** - Error messages always shown regardless of `noMsg` setting
|