HTTP
三次握手和四次挥手
2MSL:两个时间单位,一来一回。两个时间单位里如果收到消息了,说明服务器还没有关,如果两个时间单位里没有收到消息,则说明服务器已经关闭了。
http协议的构成
http协议(超文本传输协议):协议详细规定了浏览器和万维网服务器之间互相通信的规则。
请求
请求行:请求行包括三部分:请求类型,url路径,HTTP协议的版本。请求类型有get、post、delete、put 、push
请求头(request header):请求头名称:请求头内容;即为key:value格式。比如:Host:localhost;Cookie:name = baidu ;Content-type(告知服务器请求是什么类型的):application/x-www-form-urlencode;等
请求体(request body)这次请求的主体信息。如果是get请求,请求体是空的;如果是post请求,请求体可以为空可以不为空。
请求报文:请求行+请求头+空行+请求体
响应
响应行:包括三部分:HTTP协议版本,响应状态码,响应字符串
响应头(response header):格式和请求头格式一样。比如:Content-Type:text/html;charset=utf-8;Content-length:2048;Content-encoding:gzip;
属性一:content-type:内容的类型,后端向前端返回的数据类型
响应体(response body):真正的数据
响应报文:响应行+响应头+空行+响应体
开发者工具
Preview:做一个响应的预览,即响应的解析,对响应体内容解析之后的一个查看
Response:响应体,服务器返回的html内容
Headers
General
Response Headers(响应头):点击view source,得到响应行和响应头,响应体在response中
Request Headers(请求头):点击view source,就会得到请求行
From Data:当请求为post请求时,请求体携带的参数。点击 view source,原始的请求体内容
Query String Parameters(查询字符串参数),是对url中的参数做一个解析
同步异步
js特点
js是单线程的语言,对于拿到的程序,只能一行一行的执行,如果上面的代码未执行,下面的代码就只能等待,这样的代码是同步(sync)的
一段代码
结果为10,虽然定时器的时间为0,但是仍然是异步代码。异步代码总是在同步代码之后执行的。
Ajax基础
认识Ajax(Asynchronous JavaScript And XML:异步的js和xml)
Ajax前:用户触发一个http请求服务器,服务器收到后,作出响应到客户,并返回一个新的页面。所以说交互都是通过页面刷新或者页面跳转实现的。但这样的方式并不好,如果只是少量的数据更新,也会引发整个页面重新请求,浪费了很大一部分资源。
XML简介
- XML可扩展标记语言(跟HTML一样,也是由标签组成的)
- 被设计用来传输和存储数据(HTML是在网页中呈现数据的)
- XML和HTML类似,不同的是HTML中都是预定义标签,而XML中没有预定义标签,全是自定义标签,用来表示一些数据
- 以前后端向前端返回数据使用的是XML字符串,现在已经变为JSON字符串了,相对于XML,JSON更加简洁。
Ajax作用:
作用:专门用于网页和服务器之间交换数据的.(异步的javaScript和XML),是一种无需重新加载整个网页的情况下,能够更新部分网页的技术.。通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。
服务器:实质就是一台"提供了某种服务功能"的超级电脑
- 如何让电脑提供管理网站的服务?
答:安装Web服务相关的软件.例如:Apache,IIS,Tomcat,Nginx,NodeJS等 - 后端编写的代码不能直接运行,只能放到服务器对应的文件夹下,通过服务器运行
- 如何通过服务器运行:通过ip地址找到服务器对应的文件夹,然后再找到对应的文件运行
使用Ajax和不使用Ajax的区别:
- 传统的网页(即不用ajax技术的网页),想要更新内容或者提交一个表单,都需要重新加载整个网页
- 使用ajax技术的网页,通过在后台服务器进行少量的数据交换,就可以实现异步局部更新。
- 使用Ajax,用户可以创建接近本地桌面应用的直接、高可用、更丰富、更动态的Web用户界面。
Ajax的特点
优点:
- 不需要插件支持(一般浏览器只要默认开启JavaScript即可)
- 用户体验极佳(不刷新页面即可获得可更新的数据)
- 提升Web程序的性能(在传递数据方面做到按需发送,不必整体提交,允许根据用户事件来更新部分页面内容)
- 减轻服务器和带宽的负担(将服务器的一些操作转移到客户端;在传统的交互中,服务器需要给浏览器返回整个页面,在这个过程中不可避免的服务器会产生很多运算,如果有100个浏览器同时向服务器发送同样的请求,那么服务器就会做100次重复的运算,而现在有了Ajax后,前端给后端发送请求,后端只负责返回数据,真正的运算是分配给这100个浏览器去运算的,因此,对服务器的压力比较小,交互量也比较小)
缺点
- 前进,后退功能被破坏(因为Ajax永远在当前页,不会记录前后页面)
- 搜索引擎的支持度不够(因为搜索引擎爬虫还不能理解JS引起变化数据的内容,只能抓取服务器本身的数据)
- 存在跨域问题(同源)
常见的状态码
- 100-199:表示连接继续
- 200-299:表示各种意义上的成功
- 300-399:表示重定向
- 400-499:表示各种客户端错误
- 500-599:表示何种服务端错误
利用Ajax可以做什么
- 注册时,输入用户名自动检测用户是否已经存在。
- 登陆时,提示用户名密码错误
- 删除数据行时,将行ID发送到后台,后台在数据库中删除,数据库删除成功后,在页面DOM中将数据行也删除
一个比喻
页面-------------Ajax-------------后台
(顾客----------服务员-----------厨房)
在后台计算的过程中,前端页面不受任何影响,因为他是一个异步请求,并不会因此而卡顿
发送一个get请求
不携带参数时:
前端代码:
readystate是xhr对象中的属性,表示状态 ,取值为0-4。
- 0(未初始化)
- 1(open方法调用完毕)
- 2(send方法调用完毕)
- 3(服务端返回了部分结果)
- 4(服务端返回了所有结果)
<body>
<button onclick="sendMsg()">发送请求</button>
<script>
function sendMsg(){
//1.创建一个XMLHttpRequest对象
let xhr = new XMLHttpRequest();
//2.调用open方法打开连接
// open 方法有三个参数:
//1.请求的method:一般为get,post等
//2.请求的url地址
//3.是否异步,默认为true,即默认异步,故而这个参数可以不用传
xhr.open('get','./data.php');
//3.发送请求(请求体)
xhr.send();
//4.监听状态的改变
//onreadystatechange这个事件会触发很多次,所以需要判断到底哪一次代表成功
xhr.onreadystatechange = function (){
//判断状态值:0-4;4代表最终的完成
if(xhr.readyState === 4){
//判断状态码
if (xhr.status === 200){
console.log(xhr.responseText);
}
}
}
}
</script>
</body>
后端代码
<?php
echo ‘hello ajax’;
?>
返回了一个字符串
携带参数时
前端代码
<body>
<button onclick="sendMsg()">发送请求</button>
<script>
function sendMsg(){
//1.创建一个XMLHttpRequest对象
let xhr = new XMLHttpRequest();
//2.调用open方法打开连接
// open 方法有三个参数:
//1.请求的method:一般为get,post等
//2.请求的url地址
//3.是否异步,默认为true,即默认异步,故而这个参数可以不用传
xhr.open('get','./data.php?id=1);
//3.发送请求
xhr.send();
//4.监听状态的改变
//onreadystatechange这个事件会触发很多次,所以需要判断到底哪一次代表成功
xhr.onreadystatechange = function (){
//判断状态值:0-4;4代表最终的完成
if(xhr.readyState === 4){
//判断状态码
if (xhr.status === 200){
console.log(xhr.responseText);
}
}
}
}
</script>
</body>
后端代码
<?php
$id = $_GET[‘id’];
echo json_encode(array(
‘id’ => $id,
‘title’ => $’hello ajax’
))
?>
此时给前端返回的就是json格式的数据,{‘id’:’1’,’title’:’hello ajax’},实际上是一个字符串,即服务器返回的是一个满足json格式的字符串,因此需要对这个字符串进行解析
if (xhr.status === 200){
let resp = JSON.parse(xhr.responseText)
console.log(resp);
}
发送一个post请求
Get和post区别
- get的大小是有限制的,因为它的参数放在请求头的,所以大小在4k左右,而post的参数放在请求体中的,所以没有限制
- get参数是放在请求头中,而post参数是放在请求体中的
- get是明文传输,而post相对来说更安全一些
不携带参数时
前端代码
<body>
<button onclick="sendMsg()">发送请求</button>
<script>
function sendMsg(){
let xhr = new XMLHttpRequest();
//这里的方法改为:post
xhr.open('post','./data.php');
xhr.send();
xhr.onreadystatechange = function (){
if(xhr.readyState === 4){
if (xhr.status === 200){
console.log(xhr.responseText);
}
}
}
}
</script>
</body>
与get基本相同,只改变了open中的方法参数,由get改为了post
携带参数时
前端代码
除了open里写post以外,还设置了请求头,把他的Content-type设置为urlencoded这种模式,这样设置以后,在发送参数时,就可以在send里按照编码的方式来发送
后端代码
<?php
$name = $_POST[‘name’];
$age = $_POST[‘age’];
echo json_encode(array(
‘name’ => $name,
‘age’ => $age,
‘money’=> 999999
));
?>
设置请求头信息
请求行和请求体在上述代码都可以进行设置
使用setRequestHeader方法可以设置请求头,该方法接受两个参数,一个是头的名字,一个是头的值。
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
Content-Type:设置请求体内容的类型
当然,也可以自定义请求体(仅了解)
xhr.setRequestHeader('Name','zhangsan');
此时由于浏览器的安全机制会发现报错,这个时候就需要后端加一个特殊的响应头,*表示所有类型的头信息后端都能接受
response.setHeader('Access-Control-Allow-Headers','*');
如果此时还不行,因为会发送一个校验检查这个头信息可不可用。此时,后端可以将app.post改为app.all(可以接收任何类型的请求)
JSON数据响应
前端
<body>
<div id="result"></div>
<script>
//绑定键盘按下事件
window.onkeydown = function () {
const result = document.getElementById('result');
//创建对象
const xhr = new XMLHttpRequest();
//设置响应体数据的类型(自动对数据进行转化)
xhr.responseType = 'json';
//初始化
xhr.open('GET','http://127.0.0.1:3000/json-server');
//发送
xhr.send();
//事件绑定
xhr.onreadystatechange = function () {
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
// console.log(xhr.response);
// result.innerHTML = xhr.response;
//手动对数据转化
// let data = JSON.parse(xhr.response);
// console.log(data);
// result.innerHTML = data.name;
//自动转化
console.log(xhr.response);
result.innerHTML = xhr.response.name;
}
}
}
}
</script>
</body>
手动对数据转化:使用parse()方法
自动对数据转化:设置响应体数据类型xhr.responseType = 'json';
后台
//1.引入express
const express = require('express');
//2.创建应用对象
const app = express();
//3.创建路由规则
//request是对请求报文的封装
//response是对响应报文的封装
app.all('/json-server',(request,response)=>{
//设置响应头:设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
//响应一个数据
const data = {
name: 'liming'
}
//对data对象进行字符串转换
let str = JSON.stringify(data);
//设置响应体
//send方法里只能接受字符串和buffer
response.send(str);
});
//4.监听端口启动服务
app.listen(3000,()=>{
console.log('服务已经启动,3000端口监听中...');
})
AJAX-IE缓存问题
IE缓存问题:IE浏览器会对Ajax请求的结果做缓存,这样就会导致下次请求时的结果为本地的缓存,而不是最新数据。
解决方法:
发送请求时在url路径后面加一个时间戳,
xhr.open('GET','http://127.0.0.1:3000/ie?t='+Date.now());
原理:
Date.now():获取当前的时间戳
两次事件的时间戳不同,因此url也不同,那么浏览器就会认为这是两次不同的请求。这样,就会重新发一个新的请求,而不会去本地缓存中读取
AJAX请求超时与网络异常处理
请求超时回调:
xhr.ontimeout = function(){
alert('网络异常,请稍后重试!!');
}
网络异常回调:
xhr.onerror = function(){
alert('你的网络似乎出现了一些问题...')
}
btn.addEventListener('click',function () {
const xhr = new XMLHttpRequest();
//超时设置 (2s):如果2秒中之类,如果没有结果,那么这个请求就取消
xhr.timeout = 2000;
//超时回调
xhr.ontimeout = function(){
alert('网络异常,请稍后重试!!');
}
//网络异常回调
xhr.onerror = function(){
alert('你的网络似乎出现了一些问题...')
}
xhr.open('GET','http://127.0.0.1:3000/delay');
xhr.send();
xhr.onreadystatechange = function () {
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
result.innerHTML = xhr.response;
}
}
}
})
可以使用浏览器模拟网络问题:Offline断网
AJAX取消请求
使用abort()方法
<button>点击发送</button>
<button>点击取消</button>
<script>
const btns = document.querySelectorAll('button');
let xhr = null;
btns[0].onclick = function () {
xhr = new XMLHttpRequest();
xhr.open('GET','http://127.0.0.1:8080/delay');
xhr.send();
}
//取消请求
btns[1].onclick = function () {
xhr.abort();
}
</script>
AJAX重复发送问题
解决方法:设置一个标识符,做判断,将之间的请求取消掉
<button>点击发送</button>
<div id="result"></div>
<script>
const btns = document.querySelectorAll('button');
let xhr = null;
//标识变量
let isSending = false;//是否正在发送Ajax请求
btns[0].onclick = function () {
//判断标识变量:如果正在发送,就取消掉该(上一次)请求,创建新请求
if(isSending)
xhr.abort();
xhr = new XMLHttpRequest();
//修改标识符变量的值
isSending = true;
xhr.open('GET','http://127.0.0.1:3000/delay');
xhr.send();
xhr.onreadystatechange = function () {
if(xhr.readyState === 4){
//修改 标识变量的值
isSending = false;
if(xhr.status >= 200 && xhr.status < 300){
result.innerHTML = xhr.response;
}
}
}
}
</script>
Axios发送AJAX请求
Fetch发送AJAX请求(看代码)
跨域
同源策略
同源策略:是浏览器的一种安全策略
同源:协议、域名、端口号必须完全相同
违背同源策略就是跨域
如何解决跨域
JSONP
- jsonp是一个非官方的跨域请求方案,只支持get请求
- 在网页中有一些标签天生具有跨域能力,比如:img link iframe script,jsonp就是利用script标签的跨域能力来发送请求的
CORS
- CORS:跨域资源共享。CROS是官方的跨域解决方案
- 特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理
- 支持post,get请求。
- HTTP首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源
原理
CORS通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。