請求body數據處理
處理邏輯實現
./src/helpers/data.ts
import { isPlainObject } from './util'
export function transformRequest (data: any) : any {
if (isPlainObject(data)) {
return JSON.stringify(data)
}
return data
}
./src/helper/util.ts
export function isPlainObject (val: any): val is Object {
return toString.call(val) === '[object Object]'
}
加入處理流程
// ./src/index.ts
import { AxiosRequestConfig } from './types'
import xhr from './xhr'
import { buildURL } from './helpers/url'
import { transformRequest } from './helpers/data'
function axios(config: AxiosRequestConfig): void {
// TODO
processConfig(config)
xhr(config)
}
function processConfig(config: AxiosRequestConfig): void {
config.url = transformURL(config)
config.data = transformRequestData(config)
}
function transformURL(config: AxiosRequestConfig): string {
const { url, params } = config
return buildURL(url, params)
}
function transformRequestData(config: AxiosRequestConfig): any {
return transformRequest(config.data)
}
export default axios
測試
./example/base/app.ts
axios({
method: 'get',
url: '/base/get?foo=bar',
params: {
bar: 'baz'
}
})
// 請求body數據測試
axios({
method: 'post',
url: '/base/post',
data: {
a: 1,
b: 2
}
})
./examples/server.js
router.post('/base/post', (req, res) => {
res.json(req.body)
})
router.post('/base/buffer', (req, res) => {
let msg = []
req.on('data', chunk => {
if (chunk) {
msg.push(chunk)
}
})
req.on('end', () => {
let buf = Buffer.concat(msg)
res.json(buf.toJSON())
})
})
請求header數據處理
處理邏輯實現
// ./src/helpers/headers.ts
import { isPlainObject } from './util'
function normalizeHeaderName (headers: any, normalizeName: string) : void {
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): any {
normalizeHeaderName(headers, 'Content-Type')
if (isPlainObject(data)) {
if (headers && !headers['Content-Type']) {
headers['Content-Type'] = 'application/json;charset=utf-8'
}
}
return headers
}
新增類型定義
./src/types/index.ts
export interface AxiosRequestConfig {
url: string
method?: Method
data?: any
params?: any
headers?: any
}
將headers處理加入流程
./src/index.ts
function processConfig(config: AxiosRequestConfig): void {
config.url = transformURL(config)
config.headers = transformHeaders(config)
config.data = transformRequestData(config)
}
function transformHeaders (config: AxiosRequestConfig): any {
const { headers = {}, data } = config
return processHeaders(headers, data)
}
設置頭信息
// ./xhr.ts
import { AxiosRequestConfig } from './types'
export default function xhr(config: AxiosRequestConfig) {
const { data = null, url, method = 'get', headers } = config
const request = new XMLHttpRequest()
request.open(method.toUpperCase(), url, true)
Object.keys(headers).forEach(name => {
if (data === null && name.toLowerCase() === 'content-type') {
delete headers[name]
} else {
request.setRequestHeader(name, headers[name])
}
})
request.send(data)
}
測試
./example/base/app.ts
axios({
method: 'post',
url: '/base/post',
data: {
a: 1,
b: 2
}
})
axios({
method: 'post',
url: '/base/post',
headers: {
'content-type': 'application/json',
'Accept': 'application/json, text/plain, */*'
},
data: {
a: 1,
b: 2
}
})
const paramsString = 'q=URLUtils.searchParams&topic=api'
const searchParams = new URLSearchParams(paramsString)
axios({
method: 'post',
url: '/base/post',
data: searchParams
})
獲取響應數據
接口定義
// ./src/type/index.ts
export type Method =
| 'get'
| 'GET'
| 'delete'
| 'DELETE'
| 'head'
| 'HEAD'
| 'options'
| 'OPTIONS'
| 'post'
| 'POST'
| 'put'
| 'PUT'
| 'patch'
| 'PATCH'
export interface AxiosRequestConfig {
url: string
method?: Method
data?: any
params?: any
headers?: any
responseType?: XMLHttpRequestResponseType
}
export interface AxiosResponse {
data: any
status: number
statusText: string
headers: any
config: AxiosRequestConfig
request: any
}
export interface AxiosPromise extends Promise<AxiosResponse> {
}
邏輯實現
// ./xhr.ts
import { AxiosRequestConfig, AxiosPromise, AxiosResponse } from './types'
import { parseHeaders } from './helpers/headers'
export default function xhr(config: AxiosRequestConfig): AxiosPromise {
return new Promise((resolve) => {
const { data = null, url, method = 'get', headers, responseType } = config
const request = new XMLHttpRequest()
if (responseType) {
request.responseType = responseType
}
request.open(method.toUpperCase(), url, true)
request.onreadystatechange = function handleLoad () {
if (request.readyState !== 4) {
return
}
const responseHeaders = parseHeaders(request.getAllResponseHeaders())
const responseData = responseType !== 'text' ? request.response : request.responseText
const response : AxiosResponse = {
data: responseData,
status: request.status,
statusText: request.statusText,
headers: responseHeaders,
config,
request
}
resolve(response)
}
Object.keys(headers).forEach(name => {
if (data === null && name.toLowerCase() === 'content-type') {
delete headers[name]
} else {
request.setRequestHeader(name, headers[name])
}
})
request.send(data)
})
}
// ./src/helpers/headers.ts
export function parseHeaders (headers: string) : any {
let parsed = Object.create(null)
if (!headers) {
return parsed
}
headers.split('\r\n').forEach(line => {
let [key, val] = line.split(':')
key = key.trim().toLowerCase()
if (!key) {
return
}
if (val) {
val = val.trim()
}
parsed[key] = val
})
return parsed
}
./src/helpers/data.ts
export function transformResponse(data: any) : any {
if (typeof data === 'string') {
try {
data = JSON.parse(data)
} catch (e) {
//
}
}
return data
}
流程加入
// ./src/index.ts
import { AxiosRequestConfig, AxiosPromise, AxiosResponse } from './types'
import xhr from './xhr'
import { buildURL } from './helpers/url'
import { transformRequest, transformResponse } from './helpers/data'
import { processHeaders } from './helpers/headers'
function axios(config: AxiosRequestConfig): AxiosPromise {
// TODO
processConfig(config)
return xhr(config).then(res => {
return transformResponseData(res)
})
}
function processConfig(config: AxiosRequestConfig): void {
config.url = transformURL(config)
config.headers = transformHeaders(config)
config.data = transformRequestData(config)
}
function transformURL(config: AxiosRequestConfig): string {
const { url, params } = config
return buildURL(url, params)
}
function transformRequestData(config: AxiosRequestConfig): any {
return transformRequest(config.data)
}
function transformHeaders(config: AxiosRequestConfig): any {
const { headers = {}, data } = config
return processHeaders(headers, data)
}
function transformResponseData(res: AxiosResponse) : AxiosResponse {
res.data = transformResponse(res.data)
return res
}
export default axios
測試
./example/base/app.ts
axios({
method: 'post',
url: '/base/post',
data: {
a: 1,
b: 2
}
}).then(res => {
console.log(res)
})