AJAX原理
1、XMLHttpRequest
1.1 基本定义
XMLHttpRequest(简称XHR)对象,它被用于与服务器交互。
我们可以通过XHR在不刷新页面的情况下请求特定URL,获取数据。
axios库内部就是采用XHR与服务器进行交互的。
它的使用语法如下:
// 1.先创建XMLHttpRequest 对象
const xhr = new XMLHttpRequest();
// 2.配置请求方法和请求 url 地址
xhr.open("GET", "url地址");
// 3.监听 loadend 事件,接收响应结果
xhr.addEventListener("loadend", function () {
console.log(xhr.response); // 一个JSON字符串,ajax自动把它转化为对象了
});
// 4.发送请求
xhr.send(); // 发送请求一定要有,不然就类似于写了函数没调用
1.2 运用查询参数
在引用axios库后,我们使用查询参数只需要添加params
:
axios({
url: "",
params: {
pname: "",
cname: "",
},
})
使用XML对象的话,就要用以下的方式:
const pname = document.querySelector(".province").value;
const cname = document.querySelector(".city").value;
// 组织查询参数
const qObj = {
pname,
cname,
};
// 查询参数->查询参数字符串
const paramsObj = new URLSearchParams(qObj);
const querryString = paramsObj.toString();
const xhr = new XMLHttpRequest();
xhr.open("GET", `https://XXX/XXX?${querryString}`); // 手动添加到url地址?后
1.3 数据提交(请求头、请求体)
引用axios库后,添加data
参数即可:
axios({
url: "",
method: "post",
data: {
username: "1234567",
password: "7654321",
},
})
运用XHR实现的话,就要自己设置:
// 设置请求头-告诉服务器内容类型(JSON字符串)
xhr.setRequestHeader("Content-Type", "application/json");
// 要提交的数据,并转化成JSON字符串
const userObj = {
username: "1234567",
password: "7654321",
};
const userstr = JSON.stringify(userObj);
// 设置请求体
xhr.send(userstr); // 请求体写在send里面
2、Promise
2.1 基本定义
Promise
对象用于表示一个异步操作的最终完成(或失败)及其结果值。
语法:
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// 执行异步代码并传值结果
// 成功调用:resolve(值)触发 then()执行
// 失败调用:reject(值)触发 catch()执行
// resolve("模拟AJAX请求——成功结果");
reject(new Error("请求失败"));
}, 2000);
});
// 结果处理
p.then((result) => {
console.log(result);
}).catch((error) => {
console.log(error);
});
2.2 三种状态
pending
:初始状态,还没有兑现,也没有被拒绝。fulfilled
:操作成功(兑现)rejected
:操作失败(拒绝)
Promise 对象一旦被 兑现/拒绝,就无法再被改变。
// 创建Promise对象——刚创建就处于pending 待定状态
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve => 状态:'fulfilled' => then()
resolve("模拟AJAX请求-成功结果");
// reject => 状态:'rejected' => catch()
reject(new Error("模拟AJAX请求-失败结果"));
}, 2000);
});
console.log(p);
p.then((result) => {
console.log(result);
}).catch((error) => {
console.log(error);
});
3、封装简易版axios
用XMLHttpRequest和Promise对象自己封装一个简易axios,实现类似于调用axios的效果:
axios({
url: "目标资源地址",
method:'post', // 指定请求方法
data:{
// 要提交的数据
},
params:{
// 查询参数
}
}).then((result) => {
// 对服务器返回数据进行后续处理
}).catch(error=>{
// 处理错误
})
分析:
3.1 实现获取省份列表
// config就是配置对象
function myAxios(config) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(config.method || "GET", config.url);
// 使用逻辑中断,如果有设置method就用设置的,没有默认get
xhr.addEventListener("loadend", () => {
// 成功响应状态码
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response));
} else {
reject(new Error(xhr.response));
}
});
xhr.send();
});
}
myAxios({
url: "https://hmajax.itheima.net/api/province",
}).then((result) => {
document.querySelector(".my-p").innerHTML = result.list.join("<br>");
}).catch((error) => {
document.querySelector(".my-p").innerHTML = error.message;
});
3.2 实现获取地区列表
在3.1的基础上加上了查询参数的实现。
function myAxios(config) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
if (config.params) {
// 使用URLSearchParams转换,并携带到url上
const params = new URLSearchParams(config.params);
const pos = params.toString();
// console.log(pos);
config.url += `?${pos}`;
}
xhr.open(config.method || "GET", config.url);
xhr.addEventListener("loadend", () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response));
} else {
reject(new Error(xhr.response));
}
});
xhr.send();
});
}
myAxios({
url: "https://hmajax.itheima.net/api/area",
params: {
pname: "广东省",
cname: "广州市",
},
}).then((result) => {
// console.log(result);
document.querySelector(".my-p").innerHTML = result.list.join("<br>");
}).catch((error) => {
document.querySelector(".my-p").innerHTML = error.message;
});
3.3 注册用户
实现了数据的提交。
function myAxios(config) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
// 3.2实现
if (config.params) {
const paramsObj = new URLSearchParams(config.params);
const queryString = paramsObj.toString();
config.url += `?${queryString}`;
}
xhr.open(config.method || "GET", config.url);
xhr.addEventListener("loadend", () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response));
} else {
reject(new Error(xhr.response));
}
});
// 判断是否有data,携带请求体
if (config.data) {
// 转换数据类型,在send中发送
const jsonStr = JSON.stringify(config.data);
// 设置请求体内容类型标记
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(jsonStr);
} else {
xhr.send();
}
});
}
document.querySelector(".reg-btn").addEventListener("click", () => {
myAxios({
url: "https://hmajax.itheima.net/api/register",
method: "POST",
data: {
username: "12356789",
password: "1234424",
},
}).then((result) => {
console.log(result);
}).catch((error) => {
console.dir(error);
});
});