npm package: @navalink/request
Description: Dogesoft 业务请求封装库。
Latest version: 2.0.2

## Request
Dogesoft 业务请求封装库。


## Install
```shell
# with npm
npm i @ @navalink/request

# with yarn
yarn add @navalink/request
```


## Usage

### 基本使用
```tsx | pure
import $http, { EApiStatus, IResponse } from '@navalink/request';

const refreshTokenOften = async () => {
  const result = await $http.post<any, IResponse<any>>(`/api/xxx/xxx`);
  if (result.status === EApiStatus.success) {
    const data = result.data;
    // ...
  }
}
```

### 传入配置
某些场景下需要修改 axios 基础配置信息，比如 file-system 会在桌面端环境下使用不同的 url origin。
```tsx | pure
import { injectCustomization } from '@navalink/request';

injectCustomization({
  config: {
    baseURL: 'https://xxx.com',
  },
});
```

### 传递固定参数
在一些工程下，需要在每个接口内传递特定参数，比如 doty-roster 2.0 传递 app_id 信息。

```tsx | pure
import { injectCustomization } from '@navalink/request';

injectCustomization({
  baseData: {
    app_id: 'app_id value'
  }
});
```

### 定制 Response
通常，我们会根据后台接口下发的 code 区分做不同处理，比如：登录失效、没有权限等。
```tsx | pure
import { EApiStatus, injectCustomization } from '@navalink/request';

injectCustomization({
  listenResponse: (result, response) => {
    if (result.status === EApiStatus.tokenInvalid) {
      alert('请重新登录！');
    }
  }
});
```

### 动态设置 baseData
```tsx | pure
import { injectBaseData } from '@navalink/request';

injectBaseData({
  role: 'role',
});
```


### 2.0.0 的重大变更
2.0.0 升级了 axios，由 0.21.1 升级到了 1.8.3   
axios 升级后产生的影响：  
```
axios 从 0.21.4 升级到 1.8.3：

⭕️ 一、axios 1.8.3 新版特性中对现有代码产生影响的变更、及修改方案：

1、升级后的 axios 自动将请求体序列化为：
⭕️ JSON (application/json)
Multipart / FormData (multipart/form-data)
URL encoded form (application/x-www-form-urlencoded)
⭕️ 将 HTML Form 转换成 JSON 进行请求
自动转换JSON数据
- ⭕️ 只有当请求头中的 Content-Type 是 multipart/form-data 时，Axios 才会自动地将普通对象序列化成一个 FormData 对象。

产生的影响：
对于没有设置 Content-Type multipart/form-data, 即便以 FormData 形式传输的参数接，也会被自动转成 application/json 格式。

解决方案：
在请求头中设置 content-type 为 multipart/form-data;
const options = {
  method: "POST",
  headers: { "content-type": "multipart/form-data" }, // 明确设置Content-Type
  data: file.formData,
  url,
};
axios(options);

或：
$http.post<any, IResponse<IResource>>('/api/files/upload', file.formData, {
  ...config,
  headers: {
    ...config.headers,
    'Content-Type': 'multipart/form-data' // 明确设置Content-Type
  },
  adapter: customXhrUpload as AxiosAdapter
});



⭕️ 2、对进度时间的处理方式进行了改变。Axios 0.X 版本直接使用浏览器的 ProgressEvent 对象，而 1.X 版本则使用自定义的 AxiosProgressEvent 对象。

0.X 版本：
// 直接使用浏览器的 ProgressEvent
interface AxiosRequestConfig {
  onDownloadProgress?: (progressEvent: ProgressEvent) => void;
  onUploadProgress?: (progressEvent: ProgressEvent) => void;
}

1.X 版本：
// 自定义了 AxiosProgressEvent 接口
interface AxiosProgressEvent {
  loaded: number;
  total?: number;
  progress?: number; // 0-1 之间的数值
  bytes: number;    // 新增字段
  estimated?: number;
  rate?: number;
  upload?: boolean;
  download?: boolean;
}

interface AxiosRequestConfig {
  onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void;
  onUploadProgress?: (progressEvent: AxiosProgressEvent) => void;
}

所以如果代码中有用到 AxiosRequestConfig onDownloadProgress、onUploadProgress 的地方，可能会有如下报错：
没有与此调用匹配的重载。
  第 1 个重载(共 2 个)，“(type: "progress", listener: (this: XMLHttpRequest, ev: ProgressEvent<XMLHttpRequestEventTarget>) => any, options?: boolean | ... 1 more ... | undefined): void”，出现以下错误。
    类型“(progressEvent: AxiosProgressEvent) => void”的参数不能赋给类型“(this: XMLHttpRequest, ev: ProgressEvent<XMLHttpRequestEventTarget>) => any”的参数。
      参数“progressEvent”和“ev” 的类型不兼容。
        类型 "ProgressEvent<XMLHttpRequestEventTarget>" 中缺少属性 "bytes"，但类型 "AxiosProgressEvent" 中需要该属性。


解决方案：
使用新版本的类型定义，如
import { AxiosRequestConfig, AxiosProgressEvent } from 'axios';

interface ICustomConfig extends AxiosRequestConfig {
  onDownloadProgress?(progressEvent: AxiosProgressEvent): void;
  onUploadProgress?(progressEvent: AxiosProgressEvent): void;
}

function handleProgress(progressEvent: AxiosProgressEvent) {
  const percentCompleted = progressEvent.total
    ? Math.round((progressEvent.loaded * 100) / progressEvent.total)
    : 0;
  console.log(完成度: ${percentCompleted}%);
  console.log(传输速率: ${progressEvent.rate} bytes/s);
  console.log(本次传输字节: ${progressEvent.bytes});
}

如需兼容旧代码：
可以 将 config.onDownloadProgress、config.onUploadProgress 的类型定义为 any，如：
xhr.addEventListener('progress', config.onDownloadProgress as any);
xhr.upload.addEventListener('progress', config.onUploadProgress as any);



⭕️ 3、请求拦截器类型定义发生了变化，由 AxiosRequestConfig 变为 InternalAxiosRequestConfig，所以代码上需要把
import { AxiosRequestConfig } from 'axios'; // 如有用到，需要修改
instance.interceptors.request.use((config: AxiosRequestConfig) => {  // 如有用到，需要修改
const handleRequestResolve = (config: AxiosRequestConfig) => { // 如有用到，需要修改
改为：
import { InternalAxiosRequestConfig } from 'axios';
instance.interceptors.request.use((config: InternalAxiosRequestConfig) => { 
const handleRequestResolve = (config: InternalAxiosRequestConfig) => {


⭕️ 4、新版本推荐使用 common 来设置通用头部 instance.defaults.headers.common， 所以
instance.defaults.headers[method]['Content-Type'] = 'application/json; charset=utf-8';
需要改为：
instance.defaults.headers.common["Content-Type"] = 'application/json; charset=utf-8';


```