XMLHttpRequest的send方法的参数支持Document 和 BodyInit类型,BodyInit包括Blob、BufferSource、FormData、URLSearchParams、ReadableStream、USVString, 当没有数据的时候, 还可以传入null。
但是我们最常用的场景还是传一个普通对象给服务器,例如
axios({
method: 'post',
url: '/base/post',
data: {
a: 1,
b: 2
}
})
这个时候data是不能直接传给send函数的,我们需要把它转换成JSON字符串。
tranformRequest函数实现
import { isPlainObject } from "./util";
function transformRequest(data: any): any {
if (isPlainObject(data)) {
return JSON.stringify(data)
}
return data
}
export {
transformRequest
}
// 对于FormData、ArrayBuffer, 用isObject还是会判断为true,
// 但是我们这里只需要普通的JSON对象
function isPlainObject(val: any): val is Object {
return toString.call(val) === '[object Object]'
}
import { AxiosRequestConfig } from "./types";
import xhr from './xhr'
import { buildUrl } from "./helpers/url";
import { transformRequest } from "./helpers/data";
export default function axios(config: AxiosRequestConfig) {
processConfig(config)
xhr(config)
}
function processConfig(config: AxiosRequestConfig): void {
config.url = tranformUrl(config)
config.data = transformRequestData(config)
}
function tranformUrl(config: AxiosRequestConfig): string {
const { url, params } = config
return buildUrl(url, params)
}
function transformRequestData(config: AxiosRequestConfig): any{
return transformRequest(config.data)
}
至此,data就处理好了,那么接下来编写demo
import axios from '../../src/index'
axios({
method: 'post',
url: '/api/base/post',
data: {
a: 1,
b: 2
}
})
const arr = new Int32Array([21, 31])
axios({
method: 'post',
url: '/api/base/buffer',
data: arr
})
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)
})
})
我们发现 /base/buffer 的请求是可以拿到数据,但是 base/post 请求的 response 里却返回的是一个空对象,这是什么原因呢?
实际上是因为我们虽然执行 send 方法的时候把普通对象 data 转换成一个 JSON 字符串,但是我们请求header 的 Content-Type 是 text/plain;charset=UTF-8,导致了服务端接受到请求并不能正确解析请求 body 的数据。
网友评论