早期的网页
:早期的网页是由后端来渲染的(服务器端渲染 SSR)
- 客户端发出请求 =》 服务端接收并返回HTML文档 =》 页面刷新客户端加载新的HTMl文档
什么是http?
- 超文本传输协议,是一种分布式,协作式和超媒体信息系统的应用层协议;
- Http是玩维网的数据通讯基础,设计http最初是为了提供一种发布和接收HTML页面的方法;
- 通过HTTP或者HTTPS协议请求的资源由统一的标识符(URL)来标识
http是一个客户端(用户)和服务端(网站)之间请求和响应的标准
- 通过使用网页浏览器,网络爬虫或者其他的工具,客户端发起一个http请求到服务器的端口(默认80端口)我们称这个客户端用户代理程序
- 响应的服务器上存储一些资源 如HTML文件跟图片等,我们称这个响应服务器为源服务器。
HTTP的组成
一次HTTP请求主要包括:请求(Request) 响应(Response)
HTTP版本
◼ HTTP/0.9
发布于1991年;
只支持GET请求方法获取文本数据,当时主要是为了获取HTML页面内容;
◼ HTTP/1.0
发布于1996年;
支持POST、HEAD等请求方法,支持请求头、响应头等,支持更多种数据类型(不再局限于文本数据) ;
但是浏览器的每次请求都需要与服务器建立一个TCP连接,请求处理完成后立即断开TCP连接,每次建立连接增加了性能损耗;
◼ HTTP/1.1(目前使用最广泛的版本)
发布于1997年;
增加了PUT、DELETE等请求方法;
采用持久连接(Connection: keep-alive),多个请求可以共用同一个TCP连接;
◼ 2015年,HTTP/2.0
◼ 2018年,HTTP/3.0
HTTP的请求的方式
◼ 在RFC中定义了一组请求方式,来表示要对给定资源执行的操作:
- GET:GET 方法请求一个指定资源的表示形式,使用 GET 的请求应该只被用于获取数据。
- HEAD:HEAD 方法请求一个与 GET 请求的响应相同的响应,但没有响应体。
- ✓ 比如在准备下载一个文件前,先获取文件的大小,再决定是否进行下载;
- POST:POST 方法用于将实体提交到指定的资源。
- PUT:PUT 方法用请求有效载荷(payload)替换目标资源的所有当前表示;
- DELETE:DELETE 方法删除指定的资源;
- PATCH:PATCH 方法用于对资源应部分修改;
- CONNECT:CONNECT 方法建立一个到目标资源标识的服务器的隧道,通常用在代理服务器,网页开发很少用到。
- TRACE:TRACE 方法沿着到目标资源的路径执行一个消息环回测试。
◼ 在开发中使用最多的是GET、POST请求;
在后续的后台管理项目中,我们也会使用PATCH、DELETE请求;
HTTP Request Header
在request对象的header中也包含很多有用的信息,客户端会默认传递过来一些信息:
content-type是这次请求携带的数据的类型:
- application/x-www-form-urlencoded:表示数据被编码成以 '&' 分隔的键 - 值对,同时以 '=' 分隔键和值
- application/json:表示是一个json类型;
- text/plain:表示是文本类型;
- application/xml:表示是xml类型;
- multipart/form-data:表示是上传文件;
◼ content-length:文件的大小长度
◼ keep-alive:
http是基于TCP协议的,但是通常在进行一次请求和响应结束后会立刻中断;
在http1.0中,如果想要继续保持连接:
✓ 浏览器需要在请求头中添加 connection: keep-alive;
✓ 服务器需要在响应头中添加 connection:keey-alive;
✓ 当客户端再次放请求时,就会使用同一个连接,直接一方中断连接;
在http1.1中,所有连接默认是 connection: keep-alive的;
✓ 不同的Web服务器会有不同的保持 keep-alive的时间;
✓ Node中默认是5s中;
◼ accept-encoding:告知服务器,客户端支持的文件压缩格式,比如js文件可以使用gzip编码,对应 .gz文件;
◼ accept:告知服务器,客户端可接受文件的格式类型;
◼ user-agent:客户端相关的信息;
HTTP Response响应状态码
![](https://img-blog.csdnimg.cn/direct/c1202344095d478f95ebfab8e6068341.png)
响应的header中包括一些服务器给客户端的信息:
Chrome安装插件-FeHelper
AJAX发送请求
//1.创建XMLHttpRequest对象
const xhr = new XMLHttpRequest();
//2.监听对象状态的变化
xhr.onreadystatechange = function () {
console.log("状态发生了变化");
};
//3.配置请求的方式
xhr.open("GET","http://192.168.0.110:1888/01_basic/hello_text")
//4.发送请求
xhr.send();
XMLHttpRequest的state(状态)
xhr.open("GET", "http://123.207.32.32:8000/home/multidata",false);
//1.创建XMLHttpRequest对象
const xhr = new XMLHttpRequest();
//2.监听对象状态的变化
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
console.log(xhr.response)
//JSON格式的字符串解析为一个JavaScript对象的代码
console.log(JSON.parse(xhr.response));
}
console.log("状态发生了变化");
};
//3.配置请求的方式
xhr.open("GET", "http://123.207.32.32:8000/home/multidata");
//4.发送请求
xhr.send();
XMLHttpRequest其他事件监听
//1.创建XMLHttpRequest对象
const xhr = new XMLHttpRequest();
//2.onload监听数据加载完成
xhr.onload = function () {
const res = JSON.parse(xhr.response);
console.log(res);
};
//3.配置请求的方式
xhr.open("GET", "http://123.207.32.32:8000/home/multidata",false);
//4.发送请求
xhr.send();
响应数据和响应类型
//3.告诉xhr获取到的数据类型
xhr.responseType = "json";
//1.创建XMLHttpRequest对象
const xhr = new XMLHttpRequest();
//2.监听对象状态的变化
xhr.onload = function () {
// const res = JSON.parse(xhr.response);
console.log(xhr.response);
};
//3.告诉xhr获取到的数据类型
xhr.responseType = "json";
//4.配置请求的方式
xhr.open("GET", "http://123.207.32.32:8000/home/multidata", false);
//5.发送请求
xhr.send();
HTTP响应的状态status
//1.创建XMLHttpRequest对象
const xhr = new XMLHttpRequest();
//2.监听对象状态的变化
xhr.onload = function () {
// const res = JSON.parse(xhr.response);
console.log(xhr.response);
console.log(xhr.status)//200
console.log(xhr.statusText)//OK
};
//3.告诉xhr获取到的数据类型
xhr.responseType = "json";
//4.配置请求的方式
xhr.open("GET", "http://123.207.32.32:8000/home/multidata");
//5.发送请求
xhr.send();
GET/POST请求传递参数
//1.创建XMLHttpRequest对象
const xhr = new XMLHttpRequest();
//2.数据加载完成后执行的回调函数
xhr.onload = function () {
console.log(xhr.response);
};
//3.告诉xhr获取到的数据类型
xhr.responseType = "json";
//4.配置请求的方式
xhr.open(
"GET",
"http://123.207.32.32:1888/02_param/get?name=cui&age=18$address=重庆市"
);
//5.发送请求
xhr.send();
//1.创建XMLHttpRequest对象
const xhr = new XMLHttpRequest();
//2.数据加载完成后执行的回调函数
xhr.onload = function () {
console.log(xhr.response);
};
//3.告诉xhr获取到的数据类型
xhr.responseType = "json";
//4.配置请求的方式
xhr.open(
"POST",
"http://123.207.32.32:1888/02_param/posturl"
);
//发送请求体(body)
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
//5.发送请求
xhr.send("name=cui&age=18$address=重庆市");
<form action="">
<input type="text" name="username" />
<input type="password" name="password" />
</form>
<button class="btn">提交</button>
<script>
const btn = document.querySelector(".btn");
const formEL = document.querySelector("form");
btn.addEventListener("click", () => {
// console.log(form);
//1.创建XMLHttpRequest对象
const xhr = new XMLHttpRequest();
//2.数据加载完成后执行的回调函数
xhr.onload = function () {
console.log(xhr.response);
};
//3.告诉xhr获取到的数据类型
xhr.responseType = "json";
//4.配置请求的方式
xhr.open("POST", "http://123.207.32.32:1888/02_param/postform");
//发送请求体(body)
// xhr.setRequestHeader(
// "Content-Type",
// "application/x-www-form-urlencoded"
// );
//5.发送请求
const formdata = new FormData(formEL);
xhr.send(formdata);
});
//1.创建XMLHttpRequest对象
const xhr = new XMLHttpRequest();
//2.数据加载完成后执行的回调函数
xhr.onload = function () {
console.log(xhr.response);
};
//3.告诉xhr获取到的数据类型
xhr.responseType = "json";
//4.配置请求的方式
xhr.open("POST", "http://123.207.32.32:1888/02_param/postjson");
//发送请求体(body)
xhr.setRequestHeader("Content-Type", "application/json");
//5.发送请求
xhr.send(JSON.stringify({ name: "崔", age: 18 }));
ajax网络请求封装
function ajx({ url, methods = "GET", data = {}, success, failure } = {}) {
const xhr = new XMLHttpRequest();
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
success && success(xhr.response);
} else {
failure && failure(xhr.status);
}
};
//设置响应类型
xhr.responseType = "json";
const queryString = [];
//拼接url参数
if (methods.toUpperCase() === "GET") {
for (let key in data) {
queryString.push(`${key}=${data[key]}`);
}
url = url + "?" + queryString.join("&");
//设置请求方式
xhr.open(methods, url);
//设置请求头
xhr.setRequestHeader("Content-Type", "application/json");
//发送请求
xhr.send();
} else {
xhr.open(methods, url);
//设置请求头
xhr.setRequestHeader("Content-Type", "application/json");
//发送请求
xhr.send(JSON.stringify(data));
}
}
ajx({
url: "http://123.207.32.32:1888/02_param/get",
success: function (res) {
console.log(res);
},
data: { name: "崔", age: 18 },
failure: function (res) {
console.log(res);
},
});
以Promise方式返回(优化)
function ajx({ url, methods = "GET", data = {}, success, failure } = {}) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
} else {
reject(xhr.status);
}
};
//设置响应类型
xhr.responseType = "json";
const queryString = [];
//拼接url参数
if (methods.toUpperCase() === "GET") {
for (let key in data) {
queryString.push(`${key}=${data[key]}`);
}
url = url + "?" + queryString.join("&");
//设置请求方式
xhr.open(methods, url);
//设置请求头
xhr.setRequestHeader("Content-Type", "application/json");
//发送请求
xhr.send();
} else {
xhr.open(methods, url);
//设置请求头
xhr.setRequestHeader("Content-Type", "application/json");
//发送请求
xhr.send(JSON.stringify(data));
}
});
}
ajx({
url: "http://123.207.32.32:1888/02_param/get",
success: function (res) {
console.log(res);
},
data: { name: "崔", age: 18 },
failure: function (res) {
console.log(res);
},
})
.then((res) => console.log(res))
.catch((err) => console.error(err));
延迟时间timeout和取消请求
function ajx({ url, methods = "GET", data = {}, timeout, success, failure } = {}) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.timeout = timeout;
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
} else {
reject(xhr.status);
}
};
//设置响应类型
xhr.responseType = "json";
const queryString = [];
//拼接url参数
if (methods.toUpperCase() === "GET") {
for (let key in data) {
queryString.push(`${key}=${data[key]}`);
}
url = url + "?" + queryString.join("&");
//设置请求方式
xhr.open(methods, url);
//设置请求头
xhr.setRequestHeader("Content-Type", "application/json");
//发送请求
xhr.send();
} else {
xhr.open(methods, url);
//设置请求头
xhr.setRequestHeader("Content-Type", "application/json");
//发送请求
xhr.send(JSON.stringify(data));
}
});
}
ajx({
url: "http://123.207.32.32:1888/01_basic/timeout",
success: function (res) {
console.log(res);
},
timeout: 2000,
data: { name: "崔", age: 18 },
failure: function (res) {
console.log(res);
},
})
.then((res) => console.log(res))
.catch((err) => console.error(err));
如何通过封装的ajx取消请求,将xhr对象返回出去
function ajx({ url, methods = "GET", data = {}, success, failure } = {}) {
const xhr = new XMLHttpRequest();
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
success && success(xhr.response);
} else {
failure && failure(xhr.status);
}
};
//设置响应类型
xhr.responseType = "json";
const queryString = [];
//拼接url参数
if (methods.toUpperCase() === "GET") {
for (let key in data) {
queryString.push(`${key}=${data[key]}`);
}
url = url + "?" + queryString.join("&");
//设置请求方式
xhr.open(methods, url);
//设置请求头
xhr.setRequestHeader("Content-Type", "application/json");
//发送请求
xhr.send();
} else {
xhr.open(methods, url);
//设置请求头
xhr.setRequestHeader("Content-Type", "application/json");
//发送请求
xhr.send(JSON.stringify(data));
}
return xhr;
}
const xhr = ajx({
url: "http://123.207.32.32:1888/01_basic/timeout",
success: function (res) {
console.log(res);
},
data: { name: "崔", age: 18 },
failure: function (res) {
console.log(res);
},
});
btn.addEventListener("click", () => {
//取消网络请求
xhr.abort();
});
promise封装的ajx,因为返回了有resolve,reject,将xhr赋值给Promise的xhr属性,再返回promise
function ajx({
url,
methods = "GET",
data = {},
timeout,
success,
failure,
} = {}) {
const xhr = new XMLHttpRequest();
const promise = new Promise((resolve, reject) => {
xhr.timeout = timeout;
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
} else {
reject(xhr.status);
}
};
//设置响应类型
xhr.responseType = "json";
const queryString = [];
//拼接url参数
if (methods.toUpperCase() === "GET") {
for (let key in data) {
queryString.push(`${key}=${data[key]}`);
}
url = url + "?" + queryString.join("&");
//设置请求方式
xhr.open(methods, url);
//设置请求头
xhr.setRequestHeader("Content-Type", "application/json");
//发送请求
xhr.send();
} else {
xhr.open(methods, url);
//设置请求头
xhr.setRequestHeader("Content-Type", "application/json");
//发送请求
xhr.send(JSON.stringify(data));
}
});
promise.xhr = xhr;
return promise;
}
ajx({
url: "http://123.207.32.32:1888/01_basic/timeout",
success: function (res) {
console.log(res);
},
timeout: 2000,
data: { name: "崔", age: 18 },
failure: function (res) {
console.log(res);
},
})
.then((res) => console.log(res))
.catch((err) => console.error(err));
认识Fetch和Fetch API
Fetch数据的响应(Response)
Fetch网络请求的演练
// 1.fech发起get请求
fetch("http://123.207.32.32:8000/home/multidata")
.then((res) => {
//1.获取到response
const response = res;
// 2.获取具体的结果 response.json()返回一个Promise对象
response.json().then((res) => {
console.log(res);
});
})
.catch((err) => {
console.log(err);
});
// 优化一
fetch("http://123.207.32.32:8000/home/multidata")
.then((res) => {
//1.获取到response
const response = res;
// 2.获取具体的结果 response.json()返回一个Promise对象
return response.json();
})
.then((res) => console.log(res))
.catch((err) => {
console.log(err);
});
//优化二
async function getData() {
const response = await fetch(
"http://123.207.32.32:8000/home/multidata"
);
const res = await response.json();
console.log(res);
}
getData();
Fetch POST请求
![](https://img-blog.csdnimg.cn/direct/4b2760eec61a479382e482c7b763c0d2.png)
XMLHttpRequest文件上传
<input type="file" />
<button>上传</button>
<script>
const btn = document.querySelector("button");
btn.addEventListener("click", () => {
const fileEl = document.querySelector("input");
console.log(fileEl.files);
const formdata = new FormData();
formdata.append("avatar", fileEl.files[0]);
const file = fileEl[0];
const xhr = new XMLHttpRequest();
xhr.onload = () => {
console.log(xhr.response);
};
xhr.open("POST", "http://123.207.32.32:1888/02_param/upload");
xhr.send(formdata);
});
</script>
![](https://img-blog.csdnimg.cn/direct/83f0c66b4bb540eba9b76250c8e2ec5a.png)