开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情
- 我们在使用js的时候,发送请求可以使用两种原生提供的方式,fetch 或 xhr,我们使用的所有包库也都是在这基础之上进行的封装。
- 下面我们来自己封装一下 xhr, 虽然不如我们使用的 包库健壮,但是从中我们也能够学习到这种封装的思维,错误处理的逻辑等。
这个方法是可以直接使用的,我们使用 pAjax 方法,接受的参数 就是我们接口定义的 ajaxParams, url 为必填,其他项为选填,默认 请求方式为 get,我自己写项目的时候,也使用过这个方法,但如果对接口有更多的 前置 或后置处理,可能需要去使用 包库 附带的请求拦截器了,这里并没有做请求拦截器的封装。
type methodType = 'GET' | 'POST';
type dataEnum = 'string' | 'json';
export interface ajaxParams {
url:string,
method?: methodType,
async?:true,
data?: any,
headers?:Record<string|number|symbol,string>,
dataType?:dataEnum,
success?:(res:any) => any,
error?:(res:any) => any
}
function queryStringify(obj:any) {
var str = '';
for (var k in obj) {
str += k + '=' + obj[k] + '&';
}
return str.slice(0, -1);
}
function ajax(options:ajaxParams) {
if (Object.prototype.toString.call(options) !== '[object Object]') {
throw new Error('"options"需要传递一个 Object 类型数据');
}
const { url, method, async, data, headers, dataType, success, error } =
options;
if (!(method === undefined || /^(get|post)$/i.test(method))) {
throw new Error('只接受 GET 和 POST 请求');
}
if (!(async === undefined || typeof async === 'boolean')) {
throw new Error('"async" 需要传递一个布尔值');
}
if (
!(
data === undefined ||
typeof data === 'string' ||
Object.prototype.toString.call(data) === '[object Object]'
)
) {
throw new Error('"data"需要传递一个 String 或者 Object 类型数据');
}
if (
!(
headers === undefined ||
Object.prototype.toString.call(headers) === '[object Object]'
)
) {
throw new Error('"headers" 需要传递一个 Object 数据类型');
}
if (!(dataType === undefined || /^(string|json)$/i.test(dataType))) {
throw new Error('"dataType" 需要传递一个 "string" 或 "json"');
}
if (!(success === undefined || typeof success === 'function')) {
throw new Error('"success" 需要传递一个 Function 数据类型');
}
if (!(error === undefined || typeof error === 'function')) {
throw new Error('"error" 需要传递一个 Function 数据类型');
}
const _default = {
url: url,
method: method || 'GET',
async: async ?? false,
data: data || '',
headers: {
'content-type': 'application/x-www-form-urlencoded;charset=utf-8;',
...headers,
} as Record<string,any>,
dataType: dataType || 'json',
success: success || function () {},
error: error || function () {},
};
//data 如果是对象数据类型,转换成查询字符串
if (typeof data === 'object') _default.data = queryStringify(data);
//如果是get请求,并且有参数,直接组装url信息
if (/^get$/i.test(_default.method) && data)
_default.url += '?' + _default.data;
//开始请求操作
const xhr = new XMLHttpRequest();
xhr.open(_default.method, _default.url, _default.async);
xhr.onload = function () {
if (_default.dataType === 'string')
return _default.success(xhr.responseText);
try {
let result = JSON.parse(xhr.responseText);
const { data } = result
console.log('使用自己封装的方法请求',data);
_default.success(data);
} catch (err) {
_default.error(
'解析失败 ! 因为后端返回的结果不是 json 格式字符串, 请查证后再试 !!!'
);
}
};
for (let k in _default.headers)
xhr.setRequestHeader(k, _default.headers[k]);
/^get$/i.test(_default.method) ? xhr.send() : xhr.send(_default.data);
}
/**
*
* @param (ajaxParams) options
* @returns Promise
*/
export function pAjax(options:ajaxParams):Promise<any> {
return new Promise((resolve, reject) => {
ajax({
url: options.url,
data: options.data,
async: options.async,
method: options.method,
headers: options.headers,
dataType: options.dataType,
success(res: any) {
resolve(res);
},
error(err: any) {
reject(err);
},
});
});
}
export default pAjax