实现数据转换器1
转换器的作用就是实现对请求 data 和响应 data 的数据转换作用,我们在 dispatchRequest.js 函数中实现对请求数据的转换和响应数据的转换。
var utils = require("../utils");
var transformData = require("./transformData");
var defaults = require("../defaults");
module.exports = function dispatchRequest(config) {
// 确保 headers 存在
config.headers = config.headers || {};
// 转换请求数据
// config是transformData函数的this上下文
config.data = transformData.call(
config,
config.data,
config.headers,
config.transformRequest
);
// 省略中间部分代码
// ...
return adapter(config).then(
function onAdapterResolution(response) {
// 转换响应数据
// config是transformData函数的this上下文
response.data = transformData.call(
config,
response.data,
response.headers,
config.transformResponse
);
return response;
},
function onAdapterRejection(reason) {
// 响应失败的转换留到之后实现处理请求失败的功能时再做
return Promise.reject(reason);
}
);
};
我们在 core 文件夹下创建 transformData 文件,我们在里面实现 transformData 函数。
transformData 函数接收三个参数,第一个是 data,即要被转换的数据;第二个是 headers,即请求头或响应头;第三个参数 fns,即一个函数或数组,里面包含真正实现数据转换的回调函数,从上面的代码中看出是 config.transformRequest 和 config.transformResponse,我们在默认配置对象中实现这两个数组
"use strict";
var utils = require("../utils");
var defaults = require('../defaults');
/**
*
*
* @param {Object|String} data 要被转换的数据
* @param {Array} headers 请求头或响应头
* @param {Array|Function} fns 一个函数或数组,里面包含真正实现转换的回调函数
* @returns {*} 转换后的数据
*/
module.exports = function transformData(data, headers, fns) {
var context = this || defaults;
/*eslint no-param-reassign:0*/
utils.forEach(fns, function transform(fn) {
data = fn.call(context, data, headers);
});
return data;
};
我们完善defaults/index.js的转换函数功能,其中transformRequest是对请求 data 进行转换,transformResponse是对响应 data 进行转换
var utils = require("../utils");
var normalizeHeaderName = require("../helpers/normalizeHeaderName");
var transitionalDefaults = require('./transitional');
// 如果headers头没有设置Content-Type,则把value设为headers["Content-Type"]的值
function setContentTypeIfUnset(headers, value) {
if (
!utils.isUndefined(headers) &&
utils.isUndefined(headers["Content-Type"])
) {
headers["Content-Type"] = value;
}
}
// 对数据进行安全的stringify
// parser是自定义的字符串解释器来对rawValue进行解释
// encoder是自定义的字符串编码器来对rawValue进行编码
function stringifySafely(rawValue, parser, encoder) {
if (utils.isString(rawValue)) {
try {
// 如果rawValue是字符串,对其进行解释处理
// 如果不报错,则说明rawValue已被正确stringify,则去掉首尾空格,直接返回
(parser || JSON.parse)(rawValue);
return utils.trim(rawValue);
} catch (e) {
if (e.name !== 'SyntaxError') {
// 如果是自定义parser抛出的异常,则继续抛出该异常
throw e;
}
// SyntaxError为JSON.parse抛出的异常,说明rawValue没被stringify
// 继续执行,进行stringify
}
}
return (encoder || JSON.stringify)(rawValue);
}
var defaults = {
transitional: transitionalDefaults,
transformRequest: [
function transformRequest(data, headers) {
// 如果用户自定义Accept头是小写形式,则转换为'Accept'
normalizeHeaderName(headers, "Accept");
// 如果用户自定义'Content-Type'头是小写形式,则转换为''Content-Type''
normalizeHeaderName(headers, "Content-Type");
// 是以下数据类型则直接返回
if (
// FormData类型
utils.isFormData(data) ||
// ArrayBuffer类型
utils.isArrayBuffer(data) ||
// Buffer类型
utils.isBuffer(data) ||
// Stream类型
utils.isStream(data) ||
// File类型
utils.isFile(data) ||
// Blob类型
utils.isBlob(data)
) {
return data;
}
// data 是 ArrayBufferView类型
if (utils.isArrayBufferView(data)) {
return data.buffer;
}
//data 是 URLSearchParams类型,则进行序列化
if (utils.isURLSearchParams(data)) {
// 如果header没有设置'Content-Type', 则添加默认值
setContentTypeIfUnset(
headers,
"application/x-www-form-urlencoded;charset=utf-8"
);
return data.toString();
}
var isObjectPayload = utils.isObject(data);
var contentType = headers && headers['Content-Type'];
var isFileList;
// 如果data是文件列表类型,或者是object类型,但Content-Type指定为'multipart/form-data'
// 需要把data数据统一转为form-data类型
if ((isFileList = utils.isFileList(data)) || (isObjectPayload && contentType === 'multipart/form-data')) {
// 这是一个form-data npm包,用来创建'multipart/form-data'流
var _FormData = this.env && this.env.FormData;
// 把data转化为form-data类型
return toFormData(isFileList ? {'files[]': data} : data,
_FormData && new _FormData());
} else if (isObjectPayload || contentType === 'application/json') {
// data 是 object类型 或 Content-Type指定为'application/json'
// 需要对data进行字符串化
setContentTypeIfUnset(headers, 'application/json');
return stringifySafely(data);
}
},
],
transformResponse: [function transformResponse(data) {
// transitional用来指定对是否要对响应数据进行JSON.parse
// 该对象既可以由用户配置对象指定,也可以使用默认值
var transitional = this.transitional || defaults.transitional;
// 对数据进行JSON.parse时,如果有异常,是否应该抛出,默认不抛出
var silentJSONParsing = transitional && transitional.silentJSONParsing;
// 强行对数据进行JSON.parse
var forcedJSONParsing = transitional && transitional.forcedJSONParsing;
// 严格的JSON.parse,会抛出异常
var strictJSONParsing = !silentJSONParsing && this.responseType === 'json';
if (strictJSONParsing || (forcedJSONParsing && utils.isString(data) && data.length)) {
try {
return JSON.parse(data);
} catch (e) {
if (strictJSONParsing) {
throw e;
}
}
}
return data;
}],
env: {
FormData: require('./env/FormData')
},
};
我们在下一小节,实现用到的辅助函数