网络请求
Ajax
什么是 Ajax
Ajax 是一种异步请求数据的 web 开发技术,对于改善用户的体验和页面性能很有帮助。简单地说,在不需要重新刷新页面的情况下,Ajax 通过异步请求加载后台数据,并在网页上呈现出来。常见运用场景有表单验证是否登入成功、百度搜索下拉框提示和快递单号查询等等。
原理
在解释 Ajax 原理之前,我们不妨先举个“领导想找小李汇报一下工作”例子,领导想找小李问点事,就委托秘书去叫小李,自己就接着做其他事情,直到秘书告诉他小李已经到了,最后小李跟领导汇报工作。

Ajax 请求数据流程与“领导想找小李汇报一下工作”类似。其中最核心的依赖是浏览器提供的 XMLHttpRequest 对象,它扮演的角色相当于秘书,使得浏览器可以发出 HTTP 请求与接收 HTTP 响应。浏览器接着做其他事情,等收到 XHR 返回来的数据再渲染页面。

使用
1.创建 Ajax 核心对象 XMLHttpRequest
var xhr = null
if (window.XMLHttpRequest) {
// 兼容 IE7+, Firefox, Chrome, Opera, Safari
xhr = new XMLHttpRequest()
} else {
// 兼容 IE6, IE5
xhr = new ActiveXObject('Microsoft.XMLHTTP')
}
2.向服务器发送请求
xhr.open(method, url, async)
send(string) //post请求时才使用字符串参数,否则不用带参数。
- method:请求的类型;GET 或 POST
- url:文件在服务器上的位置
- async:true(异步)或 false(同步) 注意:post 请求一定要设置请求头的格式内容
xhr.open('POST', 'test.html', true)
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
xhr.send('fname=Henry&lname=Ford') //post请求参数放在send里面,即请求体
3.服务器响应处理(区分同步跟异步两种情况)
responseText 获得字符串形式的响应数据。
responseXML 获得 XML 形式的响应数据。
同步处理
xhr.open('GET', 'info.txt', false)
xhr.send()
document.getElementById('myDiv').innerHTML = xhr.responseText //获取数据直接显示在页面上
异步处理
相对来说比较复杂,要在请求状态改变事件中处理。
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
document.getElementById('myDiv').innerHTML = xhr.responseText
}
}
什么是 readyState?
readyState 是 XMLHttpRequest 对象的一个属性,用来标识当前 XMLHttpRequest 对象处于什么状态。 readyState 总共有 5 个状态值,分别为 0~4,每个值代表了不同的含义
- 未初始化 -- 尚未调用.open()方法;
- 启动 -- 已经调用.open()方法,但尚未调用.send()方法;
- 发送 -- 已经调用.send()方法,但尚未接收到响应;
- 接收 -- 已经接收到部分响应数据;
- 完成 -- 已经接收到全部响应数据,而且已经可以在客户端使用了;
什么是 status?
HTTP 状态码(status)由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP 状态码共分为 5 种类型:

常见的状态码
仅记录在 RFC2616 上的 HTTP 状态码就达 40 种,若再加上 WebDAV(RFC4918、5842)和附加 HTTP 状态码 (RFC6585)等扩展,数量就达 60 余种。接下来,我们就介绍一下这些具有代表性的一些状态码。
- 200 表示从客户端发来的请求在服务器端被正常处理了。
- 204 表示请求处理成功,但没有资源返回。
- 301 表示永久性重定向。该状态码表示请求的资源已被分配了新的 URI,以后应使用资源现在所指的- URI。
- 302 表示临时性重定向。
- 304 表示客户端发送附带条件的请求时(指采用 GET 方法的请求报文中包含 if-matched,- if-modified-since,if-none-match,if-range,if-unmodified-since 任一个首部)服务器端允许请求访问资源,但因发生请求未满足条件的情况后,直接返回 304Modified(服务器端资源未改变,可直接- 使用客户端未过期的缓存)
- 400 表示请求报文中存在语法错误。当错误发生时,需修改请求的内容后再次发送请求。
- 401 表示未授权(Unauthorized),当前请求需要用户验证
- 403 表示对请求资源的访问被服务器拒绝了
- 404 表示服务器上无法找到请求的资源。除此之外,也可以在服务器端拒绝请求且不想说明理由时使-用。
- 500 表示服务器端在执行请求时发生了错误。也有可能是 Web 应用存在的 bug 或某些临时的故障。
- 503 表示服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。
GET 和 POST 请求数据区别
- 使用 Get 请求时,参数在 URL 中显示,而使用 Post 方式,则放在 send 里面
- 使用 Get 请求发送数据量小,Post 请求发送数据量大
- 使用 Get 请求安全性低,会被缓存,而 Post 请求反之 关于第一点区别,详情见下面两张图:
fetch
与 Ajax 对比
使用 Ajax 请求一个 JSON 数据一般是这样:
var xhr = new XMLHttpRequest();
xhr.open('GET', url/file,true);
xhr.onreadystatechange = function() {
if(xhr.readyState==4){
if(xhr.status==200){
var data=xhr.responseText;
console.log(data);
}
};
xhr.onerror = function() {
console.log("Oh, error");
};
xhr.send();
同样我们使用 fetch 请求 JSON 数据:
fetch(url)
.then((response) => response.json()) //解析为可读数据
.then((data) => console.log(data)) //执行结果是 resolve就调用then方法
.catch((err) => console.log('Oh, error', err)) //执行结果是 reject就调用catch方法
从两者对比来看,fetch 代码精简许多,业务逻辑更清晰明了,使得代码易于维护,可读性更高。 总而言之,Fetch 优点主要有:
请求常见数据格式
fetch 请求本地文本数据
本地有一个 test.txt 文档,通过以下代码就可以获取其中的数据,并且显示在页面上。
function getText() {
fetch('test.txt')
.then((res) => res.text()) //注意:此处是res.text()
.then((data) => {
console.log(data)
document.getElementById('output').innerHTML = data
})
.catch((err) => console.log(err))
}
fetch 请求本地 JSON 数据
本地有个 posts.json 数据,与请求本地文本不同的是,得到数据后还要用 forEach 遍历,最后呈现在页面上。
document.getElementById('button2').addEventListener('click', getJson)
function getJson() {
fetch('posts.json')
.then((res) => res.json())
.then((data) => {
console.log(data)
let output = ''
data.forEach((post) => {
output += `<li>${post.title}</li>`
})
document.getElementById('output').innerHTML = output
})
.catch((err) => console.log(err))
}
fetch 请求网络接口
获取https://api.github.com/users中的数据,做法与获取本地 JSON 的方法类似,得到数据后,同样要经过处理
function getExternal() {
fetch('https://api.github.com/users')
.then((res) => res.json())
.then((data) => {
console.log(data)
let output = ''
data.forEach((user) => {
output += `<li>${user.login}</li>`
})
document.getElementById('output').innerHTML = output
})
.catch((err) => console.log(err))
}