目录

🌒 实现处理请求 body 数据

# 需求分析

在使用 XMLHttpRequest 对象实例 send 方法发送请求时,通过该方法的参数设置请求的 body 数据。

支持的数据类型有(XMLHttpRequest.send() - Web APIs | MDN (mozilla.org) (opens new window)): DocumnetbodyInt (包括 blobBufferSourceFormDataURLSearchParamsReadableStreamUSVString )没有数据时可以穿入 null

最常用的场景时穿入一个 普通对象。

🌰 例子:

axios({
  method: 'post',
  url: '/base/post',
  data: {
    a: 1,
    b: 2
  }
})
1
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]'
}
1
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
}
1
2
3
4
5
6
7
8

这里需要使用 isPlainObject 而不是之前的 isObject ;因为对于 FormDataArrayBuffer 这些类型, 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 ,添加处理 configdata 的逻辑:

// ... 

function processConfig(config: AxiosRequestConfig): void {
  config.url = transformURL(config)
  config.data = transformRequestData(config)
}

// ...

function transformRequestData(config: AxiosRequestConfig): any {
  return transformRequest(config.data)
}
1
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
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

第一个请求需要经过转换才能传给 XMLHttpRequestsend 方法;第二个请求不需要处理可以直接发送。

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())
  })
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

此时测试 post 发送普通对象,响应并不能显示内容,这是因为执行 send 方法时虽然转换成了 JSON 字符串发送,但是请求头 Content-Typetext/plain;charset=UTF-8 ,这里服务器端接收到请求并不能正确解析请求 body 的数据。所以要对请求头进行处理

📢 上次更新: 2022/09/02, 10:18:16