千锋教育-做有情怀、有良心、有品质的职业教育机构

领取全套视频

关注千锋学习站小程序
随时随地免费学习课程

当前位置:首页  >  技术要点  >  正文
分享到:

JavaScript全解析——什么是Ajax(下)

时间:2023-05-29 16:19      来源:千锋大连校区 作者:bjq

  什么是Ajax

      ●http 传输协议

  ○http(s) 协议规定了, 只能由前端主动发起

什么是Ajax

  ○并且在传输的过程中, 只能传递 字符串

  ●http 协议过程

  1.建立连接

  浏览器和服务器进行连接建立

  基于 TCP/IP 协议的三次握手

  2.发送请求

  要求前端必须以 请求报文 的形式发送

  报文由浏览器组装, 我们只需要提供对应的信息即可

  报文包含的内容

请求报文行
请求方式, 请求地址, 传输协议
请求报文头(对本次请求的一些说明信息)
userAgent: 请求方终端信息
accept: 期望后端返回的数据类型
content-type: 请求携带的 "材料" 的数据格式
cookie: 只要 cookie 空间内有内容, 会自动携带
请求报文空行
请求报文体(不是所有请求都有)

 

  3.接收响应

  要求后端必须以响应报文的形式返回

  报文由服务器组装

  响应报文包含的内容

  响应报文行

  响应状态码, 简单信息描述响应状态码, 传输协议

  响应报文头(对本次响应的一些说明信息)

  server: 哪一个服务器给你返回的信息

  date: 时间, 服务器时间

  content-length: 响应体长度

  content-type: 响应数据类型

  响应报文体(后端返回给前端的一些信息)

  4.断开连接

  浏览器和服务器断开连接

  基于 TCP/IP 协议的四次挥手

  ●响应状态码

  ○100199 表示连接继续

  ○200299 表示各种成功

  ○300399 表示重定向

  ○400499 表示各种客户端错误

  ○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. all
Promise.all([fn(), fn(), fn()])
.then(function () {
console.log("所有的 参数 都返回 成功状态");
}
)
.catch(function () {
console.log("这些参数中, 有一个 为 失败状态");
}
)
;
// 2. race
Promise.race([fn(), fn(), fn()])
.then(function () {
console.log("速度最快的那个执行完毕, 并且是成功状态时 执行");
}
)
.catch(function () {
console.log("速度最快的那个执行完毕, 并且是失败状态时 执行");
}
)
;
// 3. allSettled
Promise.allSettled([fn(), fn(), fn()])
.then(function (res) {
console.log(res);
}
)
.catch(function (res) {
console.log(res);
}
)
;
// 4. resolve
Promise.resolve()
.then(function (res) {
console.log("成功");
})
.catch(function (res) {
console.log("失败");
});
// 5. reject
Promise.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: "name=QF666&age=18",
});

 

  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: "name=QF666&age=18",
// 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: "name=QF666&age=18",
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)
});

 

相关文章

热门视频

开班信息

  • Unity游戏开发班--------------------

    07.13抢座

  • 网络安全培训班--------------------

    06.15抢座

  • 大数据培训班--------------------

    06.29抢座

  • 软件测试培训班--------------------

    06.15抢座

  • UI交互设计培训--------------------

    06.29抢座

  • 物联网培训班--------------------

    06.29抢座

  • Java培训班--------------------

    06.15抢座

  • 云计算培训班--------------------

    06.29抢座

  • Python培训班--------------------

    06.29抢座

  • HTML5大前端班--------------------

    06.15抢座

  • 北京总部地址:北京市海淀区宝盛北里西区28号中关村智诚科创大厦4层
    北京沙河校区:北京市昌平区沙阳路18号北京科技职业技术学院广场服务楼
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 深圳校区地址:深圳市宝安区宝安大道5010号西部硅谷B座C区1层108
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 上海校区地址:上海市宝山区同济支路199号智慧七立方3号楼2-4层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 广州校区地址:广州市白云区永平街永泰学山塘学山文化创意谷A1栋六楼
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 郑州二七区校区地址:郑州市二七区航海中路60号海为科技园C区10层
    郑州高新区校区地址:郑州市高新区金梭路与银杏路交叉口教育科技产业园南门D座4层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 大连校区地址:辽宁省大连市高新园区爱贤街10号大连设计城A座901
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 武汉金融港校区地址:武汉市东新区光谷大道77号金融港B18栋三、四层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 成都校区地址:成都市高新区肖家河沿街138号肖家河大厦三楼
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 西安校区地址:西安市雁塔区高新六路52号立人科技C座西区4楼
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 杭州旺田校区:浙江省杭州市上城区九堡镇旺田书画城A座4层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 青岛校区地址:青岛市市北区龙城路31号卓越世纪中心4号楼5层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 重庆校区地址:重庆市九龙坡区科园一路3号渝高大厦9楼
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 长沙校区地址:湖南省长沙市岳麓区麓谷企业广场A2栋三单元306号
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 哈尔滨校区地址:哈尔滨市松北区世泽路689号 科技创新城4号楼405
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 南京校区地址:南京市建邺区应天大街780号弘辉产业园1栋2层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 太原校区地址:太原市小店区长治路230号能源互联网大厦6层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 沈阳校区地址:辽宁省沈阳市浑南区世纪路16号东大软件园B园B1座A201
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 合肥校区地址:合肥市包河区徽州大道396号东方广场B座12A
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 贵阳校区地址:贵阳市云岩区延安东路37号物资大厦老楼9楼
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、网络营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 济南校区地址:济南市历下区历山路36号齐鲁师范学院利宝产业大厦3F
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python人工智能+数据分析培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、网络安全培训、区块链培训、影视剪辑包装培训、游戏原画培训、全媒体运营培训
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 千锋教育服务号

    了解千锋动态
    关注千锋教育服务号

  • 千锋教育移动站

    扫一扫快速进入
    千锋移动端页面

  • 千锋互联服务号

    扫码匿名提建议
    直达CEO信箱