林州网站建设哪家便宜,显示WordPress页面打开时长,wordpress放视频教程,只做动漫的网站什么是ajax
●认识前后端交互 ○就是 前端 与 后端的 一种通讯方式 ○主要使用的技术栈就是 ajax (async javascript and xml) ●ajax 特点 ○使用 ajax 技术网页应用能够快速的将新内容呈现在用户界面 ○并且不需要刷新整个页面, 也就是能够让页面有 无…什么是ajax
●认识前后端交互 ○就是 前端 与 后端的 一种通讯方式 ○主要使用的技术栈就是 ajax (async javascript and xml) ●ajax 特点 ○使用 ajax 技术网页应用能够快速的将新内容呈现在用户界面 ○并且不需要刷新整个页面, 也就是能够让页面有 无刷更新 的效果 ●注意点: ○前后端交互只能交互 字符串 ○并且有自己的固定步骤 创建ajax 基本步骤的是什么 1.创建 ajax 对象
const xhr new XMLHttpRequest()
2.配置 ajax 对象
// xhr.open(请求的方式, 请求的地址, 是否异步)xhr.open(GET, http://localhost:8888/test/first, true)
3.发送请求
xhr.send()
4.接收响应
xhr.onload function () { console.log(请求回来了~~~~~~~~) console.log(xhr.responseText)}
ajax 状态码有哪些
●简单来说其实就是用一个数字表明了当前 ajax 运行到哪一步了 ●语法: xhr.readyState ○0: 创建 ajax 成功 ○1: 当前 ajax 配置成功 ○2: 当前 ajax 发送成功(响应已经回到浏览器了) ○3: 表示浏览器当前正在解析本次响应, 但可能还没完成 ○4: 表示浏览器已经完成解析本次响应, 可以正常使用 responseText 了 ●0 和 1, 比较好打印, 2/3/4 这几个我们可以借助一个 事件去打印 ○readyStatechange 事件 ○通过事件名其实就可以看出, 当 readyState 发生改变时就会执行
const xhr new XMLHttpRequest()console.log(xhr.readyState) // 0
xhr.open(GET, http://localhost:8888/test/first, true)console.log(xhr.readyState) // 1
xhr.onreadystatechange function () { if (xhr.readyState 2) console.log(xhr.responseText) if (xhr.readyState 3) console.log(xhr.responseText) if (xhr.readyState 4) console.log(xhr.responseText) }
xhr.send()
ajax 常见请求方式有哪些
● GET ○表示向服务器获取资源 ●POST ○表示向服务器提交信息通常用于产生新的数据比如注册 ●PUT ○表示希望修改服务器的数据, 通常用于修改某数据 ●DELETE ○表示希望删除服务器的数据 ●OPTIONS ○发生在跨域的预检请求中表示客户端向服务器申请跨域提交 ajax 中 get 和 post 请求携带参数的方式 ●GET: 直接拼接在请求路径后, 以 ? 间隔, 使用 keyvalue 的形式书写, 当有多个参数的时候用 连接
const xhr new XMLHttpRequest()xhr.open(GET, http://localhost:8888/test/third?nameQF666age18)xhr.send()xhr.onload function () { let res JSON.parse(xhr.responseText) console.log(res)}
●POST ○在请求体内携带参数(其实就是 send 小括号内部) ○并且需要设置请求头内部的 content-type ■如果参数为 查询字符串, 需要添加: ●xhr.setRequestHeader(content-type, application/x-www-form-urlencoded) ■如果参数为 JSON 字符串, 需要添加: ●xhr.setRequestHeader(content-type, application/json)
const xhr new XMLHttpRequest()xhr.open(POST, http://localhost:8888/test/fourth)xhr.setRequestHeader(content-type, application/x-www-form-urlencoded)xhr.send(nameQF666age18)xhr.onload function () { let res JSON.parse(xhr.responseText) console.log(res)}
ajax 中 get 和 post 的区别有哪些 1.携带参数的位置 a.GET: 直接在地址后面书写 b.POST: 在请求体内书写 2.携带参数的大小 a.GET: 2kb(左右) b.POST: 原则上不限制大小, 但是服务器可以做出限制 3.携带参数的格式 a.GET: 只能携带查询字符串格式 b.POST: 原则上不限制格式, 但是需要在请求报文的 content-type 做出配置 4.安全性(相对) a.GET: 明文发送, 相对不安全 b.POST: 暗文发送, 相对安全
●http 传输协议 ○http(s) 协议规定了, 只能由前端主动发起 ○并且在传输的过程中, 只能传递 字符串
●http 协议过程 1.建立连接 浏览器和服务器进行连接建立 基于 TCP/IP 协议的三次握手 2.发送请求 要求前端必须以 请求报文 的形式发送 报文由浏览器组装, 我们只需要提供对应的信息即可 报文包含的内容 请求报文行 请求方式, 请求地址, 传输协议 请求报文头(对本次请求的一些说明信息) userAgent: 请求方终端信息 accept: 期望后端返回的数据类型 content-type: 请求携带的 材料 的数据格式 cookie: 只要 cookie 空间内有内容, 会自动携带 请求报文空行 请求报文体(不是所有请求都有) 3. 接收响应 要求后端必须以响应报文的形式返回 报文由服务器组装 响应报文包含的内容 响应报文行 响应状态码, 简单信息描述响应状态码, 传输协议 响应报文头(对本次响应的一些说明信息) server: 哪一个服务器给你返回的信息 date: 时间, 服务器时间 content-length: 响应体长度 content-type: 响应数据类型 响应报文体(后端返回给前端的一些信息) 4. 断开连接 浏览器和服务器断开连接 基于 TCP/IP 协议的四次挥手
● 响应状态码 ○ 100~199 表示连接继续 ○ 200~299 表示各种成功 ○ 300~399 表示重定向 ○ 400~499 表示各种客户端错误 ○ 500~599 表示各种服务端错误
● 回调函数 ○ 把函数 A 以实参的形式传递到 函数 B 内 ○ 在函数 B 内以形参的方式调用到 函数 A ○ 此时我们可以把函数 A 叫做函数 B 的 回调函数 ○ 我们在封装异步代码的时候会用到回调函数
function fnA () {console.log(我是 fnA 函数内部的代码)}
function fnB(callback) {callback()}
fnB(fnA)
● 使用回调函数封装一个异步代码
function fn(jinnang () {}) { console.log(班长去买水了); const timer Math.ceil(Math.random() * 3000); setTimeout(() { console.log(班长买完水了); console.log(耗时, timer); console.log(按照锦囊内的内容行事); jinnang(); }, timer);}/** * fn 函数一旦调用, 班长出发开始去买水 * 在班长出发的时候, 给他一个锦囊 */fn(() { console.log(去买一瓶牛奶);});fn();
● 上述代码已经完成了一个异步的封装
● 不过在工作中我们更多的是封装网络请求这种异步代码
● 但是我们这里通过一个 买水耗时 来模拟一个网络请求的延迟, 我们约定如果时间超过 3500 毫秒, 那么就算是失败, 否则就是成功
function fn(jinnang () {}) { console.log(班长去买水了); const timer Math.ceil(Math.random() * 3000) 2000; setTimeout(() { if (timer 3500) { console.log(请求失败, timer); } else { console.log(请求成功, timer); } }, timer);}/** * fn 函数一旦调用, 班长出发开始去买水 * 在班长出发的时候, 给他一个锦囊 */fn(() { console.log(去买一瓶牛奶);});fn();
● 此时我们已经封装完毕了, 只不过这种封装方式会带来另一个问题, 就是回调地狱
● 回调地狱: 当你使用回调函数过多的时候, 会出现的一种代码书写结构
● 需求: ○ 再买水成功后, 让班长帮忙退掉 ○ 在推掉以后, 再次让班长帮忙买水 (此时必须要在前一瓶水购买完成之后再去购买) ○ 在第二次买水成功以后, 再次让班长去买水
fn( () { console.log(班长第一次买水成功, 帮我退掉); fn( () { console.log(班长第二次买水成功); fn( () { console.log(班长第三次买水成功); }, () { console.log(班长第三次买水失败); } ); }, () { console.log(班长第二次买水失败); } ); }, () { console.log(班长第一次买水失败); });
●这段代码运行没有任何问题, 但是阅读起来极其不利于理解 ○原因: ■按照回调函数的语法进行封装, 只能通过传递一个函数作为参数来调用 ■当你使用回调函数过多的时候, 会出现回调地狱的代码结构 ○解决: ■不按照回调函数的语法封装 ■ES6 推出了一种新的封装异步代码的方式, 叫做 Promise (承诺, 期约)
Promise
是一种异步代码的封装方案 因为换了一种封装方案, 不需要安装回调函数的方式去调用, 需要按照 promise 的形式去调用 注意 promise 不是解决 异步问题的, 而是解决回调地狱问题的
●认识 Promise ○promise 的三种状态 ■持续: pending ■成功: fulfilled ■失败: rejected ○promise 的两种转换 ■从持续转为成功 ■从持续转为失败 ○promise 的基础语法 ■ES6 内置构造函数 ○promise 的语法 ■const p new Promise(function () {}) ○promise 对象可以触发的两个方法 ■p.then(函数); 成功时执行 ■p.catch(函数); 失败时执行●promise 封装一个异步函数
const p new Promise(function (resolve, reject) { // resolve: 是一个形参, 名字自定义, 值是一个函数, 当你调用的时候, 会把当前 promise 的状态转换为 成功 // reject: 是一个形参, 名字自定义, 值是一个函数, 当你调用的时候, 会把当前 promise 的状态转换为 失败 // resolve 和 reject 调用时可以传递一个参数, 这个参数会被传递给对应的 then catch const timer Math.ceil(Math.random() * 3000) 2000; setTimeout(() { if (timer 3500) { console.log(买水失败, 耗时 , timer); reject(奖励一个bug); } else { console.log(买水成功, 耗时: , timer); resolve(送你十个bug); } }, timer);});
p.then(function (address) { console.log(班长买水成功咯~~~, address);});p.catch(function (address) { console.log(班长买水失败咯~~~, address);});
● 封装 promise 为函数
function fn() { const p new Promise(function (resolve, reject) { const timer Math.ceil(Math.random() * 3000) 2000; setTimeout(() { if (timer 3500) { reject(班长买水失败); } else { resolve(班长买水成功); } }, timer); }); return p;}// 将来在使用的时候 res 得到的是 promise 的实例对象 p
const res fn();res.then(function (type) { // 这个函数执行代码 promise 状态为成功状态!!! console.log(因为, type, 谢谢班长, 我准备了20个bug, 回馈给你);});res.catch(function (type) { // 这个函数执行代码 console.log(因为, type, 谢谢班长, 我准备了800个bug, 开心死你);});
●promise 的链式调用
fn() .then(function (type) { // 这个函数执行代码 promise 状态为成功状态!!! console.log(因为, type, 谢谢班长, 我准备了20个bug, 回馈给你); }) .catch(function (type) { // 这个函数执行代码 console.log(因为, type, 谢谢班长, 我准备了800个bug, 开心死你); }); ●promise 的调用方式补充 ○如果你在第一个 then 里面返回(return) 一个新的 promise 对象的时候 ○可以在第一个 then 后面, 继续第二个 then
fn() .then(function (type) { console.log( 第一次: 因为, type, 谢谢班长, 我准备了20个bug, 回馈给你 ); return fn(); }) .then(function (type) { console.log( 第二次: 因为, type, 谢谢班长, 我准备了20个bug, 回馈给你 ); return fn(); }) .then(function (type) { console.log( 第三次: 因为, type, 谢谢班长, 我准备了20个bug, 回馈给你 ); return fn(); }) .catch(function (type) { console.log(因为, type, 谢谢班长, 我准备了800个bug, 开心死你); });
●promise 的其他方法
●Promise 实例的 finally 方法 ○不管promise是成功还是失败, 只要 promise 执行结束, 我都会执行
fn() .then(function (res) { console.log(成功); }) .catch(function (res) { console.log(失败); }) .finally(function () { console.log( 不管promise是成功还是失败, 只要 promise 执行结束, 我都会执行 ); });
● Promise 本身还有一些方法 ○all: ■作用: 可以同时触发多个 promise 行为 ●只有所有的 promise 都成功的时候, all 才算成功 ●只要任何一个 promise 失败的时候, all 就算失败了 ■语法: Promise.all([多个 promise])
○race: ■作用: 可以同时触发多个 promise 行为 ●按照速度计算, 当第一个结束的时候就结束了, 成功或失败取决于第一个执行结束的 promise ■语法: Promise.race([多个 promise])
○allSettled ■作用: 可以同时触发多个 Promise 行为 ●不管多个成功还是失败都会触发 ●会在结果内以数组的形式给你返回 每一个 promise 行为的成功还是失败 ■语法: Promise.allSettled([多个 promise])
○resolve ■作用: 强制返回一个成功状态的 promise 对象
○reject ■作用: 强制返回一个失败状态的 promise 对象
// 1. allPromise.all([fn(), fn(), fn()]) .then(function () { console.log(所有的 参数 都返回 成功状态); }) .catch(function () { console.log(这些参数中, 有一个 为 失败状态); });// 2. racePromise.race([fn(), fn(), fn()]) .then(function () { console.log(速度最快的那个执行完毕, 并且是成功状态时 执行); }) .catch(function () { console.log(速度最快的那个执行完毕, 并且是失败状态时 执行); });// 3. allSettledPromise.allSettled([fn(), fn(), fn()]) .then(function (res) { console.log(res); }) .catch(function (res) { console.log(res); });// 4. resolvePromise.resolve() .then(function (res) { console.log(成功); }) .catch(function (res) { console.log(失败); });// 5. rejectPromise.reject() .then(function (res) { console.log(成功); }) .catch(function (res) { console.log(失败); });
●async / await 上述我们已经把 promise 的基础使用掌握了, 但是个人认为, promise 的链式调用仍然会有点小问题 就是在使用的时候, 过多的链式调用, 对于阅读体验来说, 仍然是有一点小问题, 不利于阅读 所以我们可以 使用 ES6 新推出的 async与await, 使用我的异步代码书写的更像是同步代码一样 ●注意: 需要配合的必须是 Promise ●async 关键字的用法: ○直接书写在函数的前面即可, 表示该函数是一个异步函数 ○意义: 表示在该函数内部可以使用 await 关键字 ●await 关键字的用法: ○必须书写在一个有 async 关键字的函数内 ○await 后面等待的内容必须是一个 promise 对象 ○本该使用 then 接受的结果, 可以直接定义变量接受了 ●常规的 promise 调用方式
fn() .then(function (res) { console.log(res); }) .catch(function (res) { console.log(res); });
●利用 async 和 await 关键字来使用
async function newFn() { /** * await 是等待的意思 * * 在当前 fn 函数内, await 必须要等到后面的 Promise 结束以后, 才会继续执行后续代码 */ const r1 await fn(); console.log(第一次: , r1); const r2 await fn(); console.log(第二次: , r1); const r3 await fn(); console.log(第三次: , r1);}
newFn(); ●async 和 await 语法的缺点 ○await 只能捕获到 Promise 成功的状态 ○如果失败, 会报错并且终止程序的继续执行
async function newFu() { const r1 await fn(); console.log(失败后, 提示用户网络错误); // 如果失败的话这行代码并不会执行}newFu(); ● 解决方法1: 使用 try...catch... ○语法: try { 执行代码 } catch (err) { 执行的代码 } ○首先执行 try 内部的代码, 如果不报错, catch 的代码不执行了 ○如果报错, 不会爆出错误, 不会终止程序, 而是执行 catch 的代码, 报错信息在 catch 函数的形参内
async function newFu() { try { const r1 await fn(); console.log(r1); } catch (error) { console.log(网络错误, 请检查网络并重新请求); }}newFu();
●解决方法2: 改变封装的思路 ○原因: 因为 promise 对象有成功和失败的状态, 所以会在失败状态是报错 ○解决: 封装一个 百分比成功的 promise 对象, 让成功和失败的时候都按照 resolve 的形式来执行 ○只不过传递出去的参数, 记录一个表示成功或者失败的信息
function fn() { const p new Promise(function (resolve, reject) { const timer Math.ceil(Math.random() * 3000) 2000; setTimeout(() { if (timer 3500) { resolve({ code: 0, msg: 班长买水失败 }); } else { resolve({ code: 1, msg: 班长买水成功 }); } }, timer); }); return p;}
async function newFn() { const r1 await fn(); if (r1.code 0) { console.log(第一次请求失败, 请检查您的网络信息); } else { console.log(第一次请求成功, r1.msg); }const r2 await fn(); if (r2.code 0) { console.log(第二次请求失败, 请检查您的网络信息); } else { console.log(第二次请求成功, r2.msg); }}newFn();
●封装 ajax
1.ajax 封装解析 a.封装方案 i.选择回调函数 1.将来使用的时候需要按照回调函数的语法使用 2.但是容易出现回调地狱 ii.选择 promise 的形式 1.按照 Promise 的形式来使用 2.后续可以利用 async/await 语法进一步简化代码 b.决定参数 i. 请求地址(url): 必填 ii.请求方式(method): 选填, 默认 GET iii.是否异步(async): 选填, 默认 true 异步 iv.携带的参数(data): 选填, 默认 空字符 c.决定返回值 i.需要 ii.返回一个 promise 对象 1.因为需要依赖返回值来决定使用 then 还是 catch d.参数书写顺序 i.因为有多个参数, 并且有些参数可以有默认值 ii.所以我们只能通过传递一个对象的方式去处理 function ajax(options) {}
2.ajax 封装参数验证
function ajax(options {}) { // 1.1 验证参数---url 必传 if (options.url undefined) throw new Error(url 为必填项, 请填写后再试);// 1.2 验证参数---method 可以不传, 可以为 GET, 可以是 POST, 但不能是其他的 if ( !(options.method undefined || /^(GET|POST)$/i.test(options.method)) ) { throw new Error(mehtod 目前仅支持 GET 或 POST); } // 1.3 验证参数---async 可以不传, 可以为 true, 可以是 false, 但不能是其他的 if (!(options.async undefined || typeof options.async boolean)) { throw new Error(async 目前仅支持 布尔值(Boolean)); } // 1.4 验证参数---data 可以不传, 可以为一个字符串, 可以是一个对象 if ( !( options.data undefined || typeof options.data string || options.data.constructor Object ) ) { throw new Error(data 目前仅支持 字符串(String) 或 对象(Object)); }// console.log(这里执行说明参数的 url 已经传递了)}
ajax({ url: qwer, // method: POST, // async: false, data: nameQF666age18,}); 3.ajax 封装默认值
function objToStr(obj) { let str ;for (let k in obj) { str ${k}${obj[k]}; }return str.slice(0, str.length - 1);}
function ajax(options {}) { // 1 验证参数---代码省略// 2.1 处理默认值 const _options { url: options.url, // 代码执行到这里, method 要么是 undefined 要么是 GET或者POST method: options.method || GET, // 代码执行到这里, async 要么是 undefined 要么是 true 或者 false // ?? 空值运算符, 只有在 左侧为 undefined 或者 null 时才会执行右边的 async: options.async ?? true, // 代码执行到这里, data 要么是 undefined 要么是 或者 {} data: options.data || , }; // 2.2 如果当前 data 是对象, 需要转换为 查询字符串 if (typeof _options.data ! string) { _options.data objToStr(_options.data); } // 2.3 如果当前 data 有值, 且当前是 GET 方式, 那么可以提前 把 url 后拼接上 data if (_options.data /^(GET)$/i.test(_options.method)) { _options.url ? _options.data; }console.log(原始参数: , options); console.log(默认参数: , _options);// console.log(这里执行说明参数的 url 已经传递了)}
4.ajax 封装发送请求
function ajax(options {}) { // 1 验证参数---代码省略 // 2 处理默认参数---代码省略 // 3. 封装 ajax 请求 const p new Promise((resolve, reject) { // 3.1 创建 ajax const xhr new XMLHttpRequest();// 3.2 配置 ajax 请求信息 xhr.open(_options.method, _options.url, _options.async);// 3.3 配置接收响应的事件 xhr.onload function () { resolve(xhr.responseText); };// 3.4 发送本次请求 xhr.send(); }); return p;}
ajax({ url: http://localhost:8888/test/third, // method: POST, async: false, data: nameQF666age18, // data: { // name: QF666, // age: 18, // abc: 123, // },}).then((res) { console.log(res);});
5.ajax 封装请求头信息
function ajax(options {}) { // 1 验证参数---部分代码省略 // 1.5 验证参数---headers 可以不传, 可以为一个对象 if ( !( options.headers undefined || options.headers.constructor Object ) ) { throw new Error(herder 目前仅支持对象(Object)); }// 2.1 处理默认值 const _options { // code... // 代码执行到这里, headers 要么是 undefined 要么是 {} headers: { content-type: application/x-www-form-urlencoded, ...options.headers, }, };// 3. 封装 ajax 请求 const p new Promise((resolve, reject) { // 3.1 创建 ajax // 3.2 配置 ajax 请求信息 // 3.3 配置接收响应的事件// 如果当前的请求方式为 POST, 那么需要配置上对应的 请求头 if (/^(POST)$/i.test(_options.method)) { xhr.setRequestHeader( content-type, _options.headers[content-type] ); } // 如果 authorization 内有值, 需要带上 authorization if (_options.headers.authorization) { xhr.setRequestHeader( authorization, _options.headers.authorization ); } // 3.4 发送本次请求 /^(POST)$/i.test(_options.method) ? xhr.send(_options.data) : xhr.send(); }); return p;}
/** * 思考: 请求头的设置 * 当你是 post 的时候, 需要设置 content-type 字段 * 有的时候还需要设置 authorization 字段 * 有的时候还需要设置 abcd 字段 * * 例子: * 1. 登录 * POST 方式 * 需要 content-type * 不需要 authorization * 2. 获取商品列表 * GET 方式 * 不需要 content-type * 不需要 authorization * 3. 获取购物车列表 * GET 方式 * 不需要设置 content-type * 需要 authorization * 4. 修改密码 * POST 方式 * 需要 content-type * 需要 authorization */
ajax({ url: http://localhost:8888/test/third, // method: POST, // async: false, // data: nameQF666age18, data: { name: QF666, age: 18, abc: 123, }, headers: { authorization: 123 },}).then((res) { console.log(res);});
6.ajax 封装解析参数
function ajax(options {}) { // 1.6 验证参数---dataType 可以不传, 可以为 string 可以为 json if ( !( options.dataType undefined || /^(string|json)$/i.test(options.dataType) ) ) { throw new Error(dataType 目前仅支持 string 或者 json ); }// 2.1 处理默认值 const _options { // 代码执行到这里, dataType 要么是 undefined 要么是 string 要么是 json dataType: options.dataType || string, };// 3. 封装 ajax 请求 const p new Promise((resolve, reject) { // 3.3 配置接收响应的事件 xhr.onload function () { if (_options.dataType string) { resolve({ code: 1, info: xhr.responseText, msg: 成功, }); return; }try { const res JSON.parse(xhr.responseText); resolve({ code: 1, info: res, msg: 成功, }); } catch (error) { resolve({ code: 0, info: error, msg: 失败, }); } }; }); return p;}
7.ajax 封装基准地址
function outer(url) { let baseUrl url;function ajax(options {}) { // 2.1 处理默认值 const _options { url: baseUrl options.url, }; // 省略部分代码... } return ajax;}
const res outer(http://localhost:8888);
res({ url: /test/first,}).then((res) { console.log(res);});
res({ url: /test/second, dataType: json,}).then((res) { console.log(res);});
8.完整版 ajax 封装代码
function objToStr(obj) { let str ;for (let k in obj) { str ${k}${obj[k]}; }return str.slice(0, str.length - 1);}
function outer(url) { let baseUrl url;function ajax(options {}) { // 1.1 验证参数---url 必传 if (options.url undefined) throw new Error(url 为必填项, 请填写后再试);// 1.2 验证参数---method 可以不传, 可以为 GET, 可以是 POST, 但不能是其他的 if ( !( options.method undefined || /^(GET|POST)$/i.test(options.method) ) ) { throw new Error(mehtod 目前仅支持 GET 或 POST); } // 1.3 验证参数---async 可以不传, 可以为 true, 可以是 false, 但不能是其他的 if ( !(options.async undefined || typeof options.async boolean) ) { throw new Error(async 目前仅支持 布尔值(Boolean)); } // 1.4 验证参数---data 可以不传, 可以为一个字符串, 可以是一个对象 if ( !( options.data undefined || typeof options.data string || options.data.constructor Object ) ) { throw new Error(data 目前仅支持 字符串(String) 或 对象(Object)); } // 1.5 验证参数---headers 可以不传, 可以为一个对象 if ( !( options.headers undefined || options.headers.constructor Object ) ) { throw new Error(herder 目前仅支持对象(Object)); } // 1.6 验证参数---dataType 可以不传, 可以为 string 可以为 json if ( !( options.dataType undefined || /^(string|json)$/i.test(options.dataType) ) ) { throw new Error(dataType 目前仅支持 string 或者 json ); }// 2.1 处理默认值 const _options { url: baseUrl options.url, // 代码执行到这里, method 要么是 undefined 要么是 GET或者POST method: options.method || GET, // 代码执行到这里, async 要么是 undefined 要么是 true 或者 false // ?? 空值运算符, 只有在 左侧为 undefined 或者 null 时才会执行右边的 async: options.async ?? true, // 代码执行到这里, data 要么是 undefined 要么是 或者 {} data: options.data || , // 代码执行到这里, headers 要么是 undefined 要么是 {} headers: { content-type: application/x-www-form-urlencoded, ...options.headers, }, // 代码执行到这里, dataType 要么是 undefined 要么是 string 要么是 json dataType: options.dataType || string, }; // 2.2 如果当前 data 是对象, 需要转换为 查询字符串 if (typeof _options.data ! string) { _options.data objToStr(_options.data); } // 2.3 如果当前 data 有值, 且当前是 GET 方式, 那么可以提前 把 url 后拼接上 data if (_options.data /^(GET)$/i.test(_options.method)) { _options.url ? _options.data; }// 3. 封装 ajax 请求 const p new Promise((resolve, reject) { // 3.1 创建 ajax const xhr new XMLHttpRequest();// 3.2 配置 ajax 请求信息 xhr.open(_options.method, _options.url, _options.async);// 3.3 配置接收响应的事件 xhr.onload function () { if (_options.dataType string) { resolve({ code: 1, info: xhr.responseText, msg: 成功, }); return; }try { const res JSON.parse(xhr.responseText); resolve({ code: 1, info: res, msg: 成功, }); } catch (error) { resolve({ code: 0, info: error, msg: 失败, }); } };// 如果当前的请求方式为 POST, 那么需要配置上对应的 请求头 if (/^(POST)$/i.test(_options.method)) { xhr.setRequestHeader( content-type, _options.headers[content-type] ); } // 如果 authorization 内有值, 需要带上 authorization if (_options.headers.authorization) { xhr.setRequestHeader( authorization, _options.headers.authorization ); } // 3.4 发送本次请求 /^(POST)$/i.test(_options.method) ? xhr.send(_options.data) : xhr.send(); }); return p; }return ajax;}
const res outer(http://localhost:8888);
res({ url: /test/first,}).then(res { console.log(res)});
res({ url: /test/second, dataType: json}).then(res { console.log(res)});