模拟axios利用promise封装一个自己的Ajax库。
一、基础框架
封装Ajax库之前,我们要将其框架结构写出来。
我们通过一个匿名函数,将我们的核心函数暴露给全局。
对这个核心函数进行方法(get、post等)的添加。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| (function anonymous(window) { let _default = { method: "GET", url: "", baseURL: "", headers: {}, dataType: "JSON", data: null, params: null, cache: true, }; let ajaxPromise = function ajaxPromise() {}; ajaxPromise.get = function (url, options) {}; ajaxPromise.post = function (url, data, options) {}; ajaxPromise.defaults = _default; window.ajaxPromise = ajaxPromise; })(window);
|
二、 管理Ajax请求
这一步来定义发送Ajax请求。即创建XMLHttpRequest
核心对象,并发送请求。
请求发出后,根据定义的dataType
进行对返回数据的处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| let ajaxPromise = function ajaxPromise(options) { let { url, baseURL, method, data, params, dataType, headers, cache, } = options; return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest(); xhr.open(method, baseURL + url); xhr.onreadystatechange = () => { if (xhr.readyState === 4) { if (/^(2|3)\d{2}$/.test(xhr.status)) { let result = xhr.responseText; dataType = dataType.toUpperCase(); switch (dataType) { case "JSON": result = JSON.parse(result); break; case "XML": result = xhr.responseXML; break; } resolve(result, xhr); return; } reject(xhr.statusText, xhr); } }; xhr.send(data); }); };
|
在发送请求时,设置请求头。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| xhr.open(method, baseURL + url);
if (headers !== null && typeof headers === "object") { for (let attr in headers) { if (headers.hasOwnProperty(attr)) { let value = headers[attr]; if (/[\u4e00-\u9fa5]/.test(value)) { value = encodeURIComponent(value); } xhr.setRequestHeader(attr, value); } } }
|
三、 根据请求方式处理传入参数
主要根据请求方式进行传递参数的处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| if (/^(GET|DELETE|HEAD|OPTIONS)$/i.test(method)) { if (params) { url += `${ajaxPromise.check(url)}${ajaxPromise.formateDate(params)}`; } if (cache === false) { url += `${ajaxPromise.check(url)}_=${new Date()}`; } data = null; } else { if (data) { data = ajaxPromise.formateDate(data); } } return new Promise((resolve, reject) => { }
|
四、 封装方法
每一种请求方式实际上对应一个函数,因此我们可以将方法的定义修改为如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| ["get", "delete", "head", "options"].forEach((item) => { ajaxPromise[item] = function anonymous(url, options) { options = { ..._default, ...options, url: url, method: item.toUpperCase(), }; return ajaxPromise(options); }; });
["post", "put", "patch"].forEach((item) => { ajaxPromise[item] = function anonymous(url, data = {}, options = {}) { options = { ..._default, ...options, url: url, method: item.toUpperCase(), data: data, }; return ajaxPromise(options); }; });
|
五、 正常使用
封装好我们的Ajax库之后,可以使用一言接口简单的测试一下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="ajaxPromise.js"></script> </head>
<body> <script> ajaxPromise.get('https://v1.hitokoto.cn/').then(result => { console.log(result.hitokoto); document.write(`<p>${result.hitokoto}</p>`) }) </script> </body>
</html>
|