AJAX核心知识
所有的思路都在代码中
AJAX:核心 基于 XMLHttpRequest创建HTTP请求
- 创建 XHR实例
- 打开一个URL地址 【发送前的配置信息等】
method请求方式 GET/DELETE/head/options… , POST (post/put/patch…) GET 和 POST 在官方定义中 没有明确区别的 但是浏览器或者开发的时候,都有一套约定俗成的规范:
GET请求 传递给服务器的数据 除请求头以外 要求基于URL问号传参 POST请求 数据一般是通过请求体传递 send(“name=zs&age=22”) @1 GET传递的信息不如POST多 因为URL有长度限制 [IE 2KB chrome 大概是8KB] 超过这个长度的信息会被自动截掉 这样导致传递的信息是不完整的 POST 理论上是没有限制的,但是数据越多,传输速度越慢,越消耗时间, 这样可能导致浏览器报传输超时的错误,所有我们实际上会自己手动做限制 @2 GET请求会产生缓存 [浏览器的默认行为,不可控的缓存]:两次请求及以上,请求相同的API接口, 并且传递的参数也一样,浏览器请求的信息会直接返回,而不是从服务器获取最新的数据! open(“GET”, “URL?name=mao&age=22&_”+Math.random()) 在请求URL的末尾设置随机数,以此来清除GET缓存的副作用(不是清除缓存 是不走缓存) @3 POST相对于GET来说更安全一些,GTE传递的信息是基于URL末尾拼接,这个随便做一些劫持或者修改, 都可以直接改了,而POST请求主体信息的劫持,没那么好做,但是 “互联网面前 人人都在裸奔!” 所以不管是什么请求方式 只要设计安全的信息,都需要手动加密,(所有传递的信息默认情况下都是明文的)
url 请求URL
async 是否采用异步 默认情况下 是true
username 需要的用户名
password 密码
监听请求的过程,在不同阶段做不同的处理(包含获取服务器的响应信息) @1 ajax的状态 xhr.readyState ajax的状态 0 未发送 unsend 1 opened 初始化一个请求 2 headers_received 收到请求头信息 3 loading 响应主体信息在处理中(接收响应数据中) 4 done 响应数据收到完毕(响应主体数据已经返回)
@2 HTTP状态码 xhr.status
200 OK
202 服务器接收 还未处理请求
204 服务器已处理 但不需要返回响应主体内容
206 断点续传(用得少)
301 永久转移(重定向 域名迁移)
302 暂时转移 (负载均衡)
304 缓存
305 用户代理
400 请求参数有误
401 未授权
403 服务器拒绝执行 可能会以响应主体返回原因
404 地址错误
405 请求方式不允许
408 请求超时
500 服务器内部错误
503 服务器超负荷
505 http版本不支持
@3 获取响应主体信息
1. xhr.response 响应的内容 (返回的是什么 就是什么)
2. xhr.responseText 文本形式
3. xhr.responseXML xml格式的内容
4. 文件流格式数据 [buffer / 二进制...]
@4 获取响应头信息
1. xhr.getResponseHeader(name) 参数name就是需要获取的请求头名称
2. xhr.getAllResponseHeaders 直接获取所有请求头
- 发送请求 [send中传递的信息 就是设置的请求主体中的信息]
基于请求主体传递给服务器的数据格式是有要求的 - form-data 主要应用于文件的上传 new FormData 或者表单提交
需要设置请求头的content-type类型是 multipart/form-data - x-www-form-urlencoded 格式的字符串 “name=age&age=22” 和get请求传参格式一样
请求头的content-type类型也需要更改为 application/x-www-form-urlencoded Qs库 npm install qs Qs.stringfy/parse 实现对象和urlencoded格式字符串之间的转换 - raw 未加工的数据 就是字符串格式
支持: @1 普通字符串 text/plain @2 js代码字符串 application/javascript @3 JSON字符串 application/json @4 xml格式 application/xml @… - binary 二进制格式 【buffer 二进制…】
一般用于文件上传 图片 image/jp(e)g excel application/… - GraphQL
监听方法: onload 信息返回 但是http状态码 不一定是200 onerror 信息没有返回 什么都拿不到 比如可能是断网了 onreadystatechange 只要 readyState 属性发生变化 则触发 xhr 总共有7个可用的方法
let xhr = new XMLHttpRequest;
xhr.open("GET", "./01-data.json");
xhr.onreadystatechange = function () {
if (xhr.status === 200 && xhr.readyState === 4) {
console.log(xhr.response)
console.log(xhr.responseText)
console.log(xhr.getResponseHeader("content-type"))
}
}
xhr.send()
倒计时抢购案例
所有的思路都在代码中
样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.box {
width: 400px;
height: 60px;
line-height: 60px;
text-align: center;
background-color: skyblue;
margin: 100px auto;
letter-spacing: 2px;
font-size: 20px;
}
.text {
color: rgb(211, 19, 19);
font-weight: 600;
}
</style>
</head>
<body>
<div class="box">距离抢购还剩下:
<span class="text">00:00:00</span>
</div>
<script src="./02-倒计时抢购.js"></script>
</body>
</html>
核心逻辑
const countdownModule = (() => {
const textBox = document.querySelector(".text");
let serverTime = 0;
let targetTime = +new Date() + 1000 * 60 * 60;
let timer;
const queryServerTime = function queryServerTime() {
return new Promise(resolve => {
const xhr = new XMLHttpRequest;
xhr.open("head", "./01-data.json");
xhr.onreadystatechange = function () {
if (xhr.readyState === 2 && (xhr.status >= 200 && xhr.status < 300)) {
resolve(+new Date(xhr.getResponseHeader("date")));
}
}
xhr.send(null);
});
}
const computed = () => {
let diff = targetTime - serverTime;
let hours, minuter, seconds;
if (diff <= 0) {
textBox.innerHTML = "00:00:00";
clearInterval(timer);
return;
}
hours = Math.floor(diff / (1000 * 60 * 60));
minuter = Math.floor((diff = diff - hours * 1000 * 60 * 60) / (1000 * 60));
seconds = Math.floor((diff = diff - minuter * 1000 * 60) / 1000);
textBox.textContent = `${("" + hours).padStart(2, 0)}:${("" + minuter).padStart(2, 0)}:${("" + seconds).padStart(2, 0)}`;
}
return {
async init() {
serverTime = await queryServerTime();
computed();
timer = setInterval(() => {
serverTime += 1000;
computed();
}, 1000);
}
}
})();
countdownModule.init();
|