🌒 实现处理请求 body 数据
# 需求分析
在使用
XMLHttpRequest
对象实例send
方法发送请求时,通过该方法的参数设置请求的body
数据。支持的数据类型有(XMLHttpRequest.send() - Web APIs | MDN (mozilla.org) (opens new window)):
Documnet
、bodyInt
(包括blob
、BufferSource
、FormData
、URLSearchParams
、ReadableStream
、USVString
)没有数据时可以穿入null
;
最常用的场景时穿入一个 普通对象。
🌰 例子:
axios({
method: 'post',
url: '/base/post',
data: {
a: 1,
b: 2
}
})
2
3
4
5
6
7
8
此时的
data
不能直接传给send
方法,需要先转换为 JSON 字符串。
# transformRequest
函数实现
根据需求分析需要实现一个工具函数,对 request
中的 data
进行转换。
文件 src/helpers/util.ts
中添加判断是否为普通对象的方法:
export function isPlainObject(val: any): val is Object {
return toString.call(val) === '[object Object]'
}
2
3
新建文件 src/helpers/data.ts
:
import { isPlainObject } from './util'
export function transformRequest(data: any): any {
if(isPlainObject(data)) {
return JSON.stringify(data)
}
return data
}
2
3
4
5
6
7
8
这里需要使用
isPlainObject
而不是之前的isObject
;因为对于FormData
、ArrayBuffer
这些类型,isObject
也为true
,而这些数据是不必处理的。所以转换应该只对 普通对象有效。
修改
src/helpers/url.ts
中的类型判断:if (isDate(val)) { val = val.toISOString() } else if(isPlainObject(val)) { val = JSON.stringify(val) }
1
2
3
4
5这样才更加合理。
# 在入口文件加入请求 body
处理逻辑
在上一节的基础上的 src/index.ts
,添加处理 config
中 data
的逻辑:
// ...
function processConfig(config: AxiosRequestConfig): void {
config.url = transformURL(config)
config.data = transformRequestData(config)
}
// ...
function transformRequestData(config: AxiosRequestConfig): any {
return transformRequest(config.data)
}
2
3
4
5
6
7
8
9
10
11
12
# 编写测试 DEMO
在 examples/base/app.ts
,添加新的请求:
axios({
method: 'post',
url: '/base/post',
data: {
a: 1,
b: 2
}
})
const arr = new Int32Array([21, 31])
axios({
method: 'post',
url: '/base/buffer',
data: arr
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
第一个请求需要经过转换才能传给
XMLHttpRequest
的send
方法;第二个请求不需要处理可以直接发送。
在 examples/server.js
添加两个路由处理这两个请求, 返回请求穿入的数据:
router.post('/base/post', function(req, res) {
res.json(req.body)
})
router.post('/base/buffer', function(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())
})
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
此时测试
post
发送普通对象,响应并不能显示内容,这是因为执行send
方法时虽然转换成了 JSON 字符串发送,但是请求头Content-Type
是text/plain;charset=UTF-8
,这里服务器端接收到请求并不能正确解析请求body
的数据。所以要对请求头进行处理