处理 params
params参数value为以下类型需要处理:
- 数组 key 需要加上[]
- 对象 JSON.stringfy()
- 日期Date类型
- 特殊字符, 如空格等…
- 空值忽略
- url中hash标记
- 保留url已经存在的参数 ```typescript import { isDate, isObject, encode } from “./util”
export function buildRUL(url: string, params?: any): string { if (!params) { return url }
const parts: string[] = []
Object.keys(params).forEach(key => {
const value = params[key]
if (value === undefined || value === null) {
return
}
// 统一处理为数组
let values = []
if (Array.isArray(value)) {
key += ‘[]’
values = value
} else {
values = [value]
}
// 拼接参数
values.forEach(val => {
if (isDate(val)) {
val = (val as Date).toISOString()
}
if (isObject(val)) {
val = JSON.stringify((val as Object))
}
parts.push(${encode(key)}=${encode(val)})
})
})
let serializedParams = parts.join(‘&’)
if (serializedParams) {
// 去掉锚点# (对于后端没有用)
const markIndex = url.indexOf(‘#’)
if (markIndex !== -1) {
url = url.slice(0, markIndex)
}
// 如果有? 继续拼接&,否则加上 ?
url += url.indexOf(‘?’) !== -1 ? &${serializedParams} : ?${serializedParams}
}
return url
}
<a name="fa0b6665"></a>## 处理 data<a name="1bc972b5"></a>### 表单数据提交常见格式1. 默认 application/x-www-form-urlencoded1. multipart/form-data,不对字符编码。在使用包含文件上传控件的表单时,必须使用该值<a name="22fd4789"></a>### Content-Type 定义提交数据类型1. json 格式字符串:application/json1. 默认 application/x-www-form-urlencoded1. 文件上传:multipart/form-data<a name="301aa4f6"></a>### 转换 data 数据1. 如果数据为普通对象,转成 json 格式字符串,1. 请求头需要把content-type: application/json```typescriptexport function transformRequest(data: any) {if (isPlainObject(data)) {return JSON.stringify(data)}return data}
处理 headers
- 如果传入为普通对象,设置 Content-Type 为 application/json
- 定义函数 normalizeName,处理传入 headeres 的 key 大小写问题 ```typescript import { isPlainObject } from “./util”;
// 处理headername 大小写问题 function normalizeHeaderName(headers: any, normalizeName: string) { if (!headers) { return }
Object.keys(headers).forEach(name => { if (name !== normalizeName && name.toUpperCase() === normalizeName.toUpperCase()) { headers[normalizeName] = headers[name] delete headers[name] } }) }
export function processHeaders(headers: any = {}, data: any) { normalizeHeaderName(headers, ‘Content-type’)
if (isPlainObject(data) && !headers[‘Content-Type’]) { headers[‘Content-Type’] = ‘application/json’ }
return headers }
<a name="9bfb9bcb"></a>## 处理 Response<a name="drBt3"></a>### 响应头headers通过`request.getAllResponseHeaders()`获取的headers数据:
connection: keep-alive content-length: 66 content-type: application/json; charset=utf-8 date: Mon, 23 May 2022 16:45:28 GMT etag: W/“42-B3q+nueBZBTNpq/cPd3/uIemlRo” keep-alive: timeout=5 x-powered-by: Express
把以上数据处理为一个对象```typescript// 转换 responseHeadersexport function parseHeaders(headers: string) {const headerOjb = Object.create(null)if (!headerOjb) {return headerOjb}// 通过换行符分割headers.split('\r\n').forEach(row => {const [key, value] = row.split(':')if (key) {headerOjb[key.trim().toLowerCase()] = (value || '').trim()}})return headerOjb}
响应数据 data
响应数据都试着转成json格式
export function transformResponse(data:any){
if(typeof data === 'string'){
try {
data = JSON.stringify(data)
} catch (error) {
// 转换失败
}
}
return data
}
响应结果合并
export interface AxiosResponse {
headers: any,
status: number
data: any,
config: AxiosRequestConfig,
request: any,
}
import { parseHeaders } from './helpers/headers'
import { AxiosPromise, AxiosRequestConfig, AxiosResponse } from './types'
export default function xhr(config: AxiosRequestConfig): AxiosPromise {
return new Promise((resolve, reject) => {
const { url, method = 'get', data = null, headers, responseType } = config
const request = new XMLHttpRequest()
if (responseType) {
request.responseType = responseType
}
request.open(method.toLowerCase(), url, true)
// 设置请求头
Object.keys(headers).forEach(name => {
if (data === null && name.toLowerCase() === 'content-type') {
delete headers[name]
} else {
request.setRequestHeader(name, headers[name])
}
})
request.onreadystatechange = event => {
if (request.readyState !== 4) {
return
}
const responseData = responseType === 'text' ? request.responseText : request.response
const response: AxiosResponse = {
headers: parseHeaders(request.getAllResponseHeaders()),
status: request.status,
data: responseData,
request: request,
config
}
resolve(response)
}
request.onerror = err => {
reject(err)
}
request.send(data)
})
}
