Ajax学习笔记

  1. 1. 认识AJAX
    1. 1.1. ajax简介
    2. 1.2. AJAX的特点
      1. 1.2.1. AJAX的优点
      2. 1.2.2. AJAX的缺点
    3. 1.3. 常见使用ajax网站
  2. 2. 了解HTTP协议
    1. 2.1. 请求报文
    2. 2.2. 响应报文
    3. 2.3. XML简介
  3. 3. 服务器搭建
    1. 3.1. express
      1. 3.1.1. 搭建步骤
    2. 3.2. nodemon
      1. 3.2.1. 安装
  4. 4. Ajax的使用
    1. 4.1. 原生AJAX
      1. 4.1.1. 参数传递
      2. 4.1.2. 设置请求头
      3. 4.1.3. 服务端响应JSON数据
      4. 4.1.4. IE缓存机制
      5. 4.1.5. 请求超时和网络异常处理
      6. 4.1.6. 取消请求
      7. 4.1.7. 请求重复发送
    2. 4.2. jQuery封装的AJAX
      1. 4.2.1. 通用方法
    3. 4.3. Axios的AJAX
      1. 4.3.1. 使用axios
  5. 5. 跨域
    1. 5.1. 同源策略
    2. 5.2. JSONP
      1. 5.2.1. JSONP工作原理
      2. 5.2.2. JSONP的使用
    3. 5.3. CORS
      1. 5.3.1. CORS工作原理
      2. 5.3.2. CORS的使用

认识AJAX

ajax简介

AJAX全称为Asynchronous JavaScript And XML,就是异步的JS和XML。通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。AJAX不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。

AJAX的特点

AJAX的优点

  1. 可以无需刷新页面而与服务器进行通信。
  2. 允许你根据用户事件来更新部分页面内容。

AJAX的缺点

  1. 没有浏览历史,不能回退。
  2. 存在跨域的问题(同源)
  3. SEO不友好

常见使用ajax网站

百度的注册页面,输入已经注册的名字会返回false提示该名称已被使用。

ProcessOn网站,在线绘制图像。

今日头条下拉到底部会刷新出新的头条进行观看。

百度搜索时,输入几个字会有下拉框提示相关的关键字。

京东界面的二级菜单栏也是由ajax发送的数据。

ajax实际上是一种懒加载的模式。懒加载:用则加载,不用则不加载。

了解HTTP协议

HTTP(hypertext transport protocol)协议,即超文本传输协议,协定详细规定了浏览和万维网服务器之间的通信规则。

请求报文

重点是格式与参数,结构都是相同的

1
2
3
4
5
6
7
GET /s?ie=utf-8 HTTP/1.1    		行
Host: atguigu.com 头
Cookie: name=guigu
Content-type: application/x-www-form-urlencoded
User-Agent: chrom 83
空行
username=admin&password=admin 体

响应报文

1
2
3
4
5
6
7
8
9
10
11
12
HTTP/1.1 200 OK						 行
Content-Type: text/html;charset=utf-8 头
Contetn-Length: 2048
Content-Encoding: gzip
空行
<html> 体
<head>
</head>
<body>
<h1>I am the Bone of my Sword</h1>
</body>
</html>

XML简介

XML即可扩展标记语言。XML被设计用来传输和存储数据。XML和HTML类似,不同的是HTML中都是预定义标签,而XML中没有预定义标签,全都是自定义标签,用来表示一些数据。

比如我又一个学生数据:

1
2
3
name:'孙悟空',
age:18,
gender='男';

用XML表示:

1
2
3
4
5
<student>
<name>孙悟空</name>
<age>18</age>
<gender></gender>
</student>

不过现在已经被JSON取代:

1
2
3
4
5
{
name:'孙悟空',
age:18,
gender='男';
}

服务器搭建

express

因为ajax需要给服务端发送请求,而express正好可以搭建一个服务端,以便后续ajax请求的发送和接收。

express是基于node.js的,所以要安装好node.js,再执行以下操作。

搭建步骤

在VScode下打开终端,在终端中输入命令

1
2
npm init --yes    		//用于初始化
npm i express //安装express

执行完后再js文件中编写express服务机代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//引入express
const express = require('express');
//创建应用对象
const app = express();
//创建路由规则
//request是对请求报文的封装
//response是对响应报文的封装
app.get('/server',(request,response)=>{
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
//设置响应体
response.send('HELLO EXPRESS');
});
app.post('/server',(request,response)=>{
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
//设置响应体
response.send('HELLO AJAX POST');
});
//监听端口启动服务
app.listen(8360,()=>{
console.log('服务已经启动,8360端口监听中。。。');
})

在终端执行node xxx.js开启服务器,服务则会在设定的端口下启动,可以在浏览器中输入127.0.0.1:8360/server访问到。

1
node server.js					//开启服务器

nodemon

express每次修改js文件都需要关闭服务,保存,然后再次启动。如果调试频繁,来回重启很麻烦,所以使用nodemon包:这个包可以监测文件变化,并自动保存重启。

安装

同样是需要node的npm环境,在终端命令行输入

1
npm install -g nodemon

服务器的启动也不再用node xxx.js,使用命令:

1
nodemon server.js

这时运行的服务器再次访问,修改内容无需重启服务器,内容也能改变。

Ajax的使用

原生AJAX

原生ajax的使用依赖于XMLHttpReques对象。话不多说,直接上代码,一看就懂。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//1.创建对象
const xhr = new XMLHttpRequest();
//2.初始化,设置请求方法和url
xhr.open('GET','http://127.0.0.1:8360/server');
//3.发送请求
xhr.send();
//4.事件绑定,处理服务端返回的结果
xhr.onreadystatechange = function(){
//readyState是xhr对象中的属性,表示状态0 1 2 3 4
//等于4表示服务端返回了所有的结果
if(xhr.readyState === 4){
//判断响应状态码,2开头都表示成功
if(xhr.status>=200 && xhr.status<300){
//处理响应结果
console.log(xhr.status);//状态码
console.log(xhr.statusText);//响应状态字符串
console.log(xhr.getAllResponseHeaders);//响应头(所有的)
console.log(xhr.response);//响应体
}
}
}

open()方法中第一个参数写GET就是GET请求,写POST就是POST请求,也可以写ALL。

send()方法中可以设置请求体,内容可以任意设置,但还是要根据需求来。

参数传递

在URL末尾添加一个问号,以&隔开不同的参数,如下:

1
http://127.0.0.1:8360/server?user=admin&password=admin

设置请求头

1
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')

上面这个内容不用管,这个方法设置后能够传入一个请求头,两个参数分别是请求头的名称和内容。一般可以把身份信息校验放到头部信息,当然这个也可以任意设置,但还是按需求来。

服务端响应JSON数据

无非是服务端返回的数据换成JOSN数据,服务端将JSON数据序列化成字符串,再返回给客户端。response.send(jsonStr)。客户端接收到之后再对数据进行处理。代码如下:

服务端的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const express = require('express');
const app = express();
app.all('/json-server',(request,response)=>{
response.setHeader('Access-Control-Allow-Origin','*');
response.setHeader('Access-Control-Allow-Header','*');
const data = {
name:'孙悟空',
age:18
}
let str = JSON.stringify(data);//将JOSN序列化
response.send(str);//响应给客户端
});
app.listen(8360,()=>{
console.log('服务已经启动,8360端口监听中。。。');
})

客户端接收并处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const result = document.getElementById('result');
result.addEventListener('mouseover',function(){
const xhr = new XMLHttpRequest();
xhr.open('POST','http://127.0.0.1:8360/json-server');
//如果没有下面这一行,就需要自己反序列化数据
xhr.reponseType = 'json';
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status>=200 && xhr.status<300){
//let data = JSON.parse(xhr.response)
console.log(xhr.response);//不出意外会得到服务器创建的对象
}
}
}
});

IE缓存机制

IE浏览器会对ajax请求结果做一个缓存,再去发送请求的时候走的就是本地的缓存,而不是服务器的响应。

解决方式

在请求链接中传入一个参数,使每时每刻的参数不相同,IE就会认为是不同的请求,就不会走缓存,每一次都会重新发送请求。

1
xhr.open("get",'http://127.0.0.1:8360/ie-server?ie='+Date.now());

但是这个做法在实际中是不会用的。

请求超时和网络异常处理

程序运行中时常会有网络超时的情况,服务端不能保证及时快速的反应,所以在请求超时和网络异常的时候给用户提醒,增加产品的体验。

此类问题可以调用XMLHttpRequest包的方法onerror()和ontimeout()来解决:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const xhr = new XMLHttpRequest();
xhr.open('POST','http://127.0.0.1:8360/error-server');
//超时设置2s
xhr.timeout = 2000;
//超时回调
xhr.ontimeout = function(){
alert("网络异常,请稍后重试!");
}
//网络异常回调
xhr.onerror = function(){
alert("你的网络似乎出现了一些问题!");
}
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status>=200 && xhr.status<300){
console.log(xhr.response);
}
}
}

取消请求

请求过程中,在请求发送之后,但是在接收到响应之前,可以通过代码将请求取消掉。

取消请求使用abord()方法

1
xhr.abord();

请求重复发送

有时服务器响应较慢,用户频繁点击发送请求,让服务器接收到很多个重复的请求,服务器压力增大。这个问题可以设置用户重复点击会关闭上一个请求,重新发送一个新的请求。

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var btn = document.getElementById('btn');
let xhr = null;
//标识是否放松ajax请求
let isSending = false;
btn.onclick = function(){
if(isSending) xhr.abord();
xhr = new XMLHttpRequest();
//修改标识变量的值
isSending = true;
xhr.open('GET','http://127.0.0.1:8360/delay');
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
//标识修改变量
isSending = false;
}
}
}

jQuery封装的AJAX

除了原生的ajax,jQuery也封装了ajax,格式是这样的:

1
2
3
4
5
6
$.get(url,[data],[callback],[type]);
//这里get可以使用post,就是指get请求和post请求
//url:请求的url地址
//data:请求携带的参数
//callback:载入成功时的回调函数
//type:设置返回内容格式,有html、xml、script、json、text、default

看一个实例就差不多了:

1
2
3
4
5
6
7
8
9
$('button').eq(0).click(function(){
$.get(//请求方式
'http://127.0.0.1:8360/jquery-server',//请求地址
{admin:admin,passwrod:admin},//传入的参数
function(data){//回调函数,这里参数data即响应体
console.log(data);
},
'json');//返回内容格式
});

通用方法

使用ajax()方法发送请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$.ajax({
//url地址
url:'http://127.0.0.1/8360/jquery-server',
//传递的参数
data:{admin:admin,password:admin},
//请求类型
type:'GET',
//返回数据类型
dataType:'json',
//成功时的回调函数
success: function(data){
console.log(data);
},
//超时时间
timeout:2000,
//失败的回调
error: function(){
console.log('出错了');
},
//头信息
headers:{
a:400,
b:600
}
});

这里只列举了一部分,更多的可以查jQuery文档

Axios的AJAX

axios是目前前端最热门的ajax工具库,使用频率很高,vue和react强烈推荐。

特点:

  1. 支持浏览器和node.js
  2. 支持promise
  3. 能拦截请求和响应
  4. 能转换请求和响应数据
  5. 能取消请求
  6. 自动转换JSON数据
  7. 浏览器端支持防止CSRF(跨站请求伪造)

使用axios

使用可以在页面中链入axios的CDN链接

1
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.0/axios.min.js"></script>

跨域

同源策略

同源策略(Same-Origin Policy)是最早由Netscape公司提出,是浏览器的一种安全策略。

同源:当前网页和ajax请求的目标资源之间的url,两者之间的协议、域名、端口号必须完全相同。

注:ajax是默认遵循同源策略的,而违背同源策略无法发送ajax,称为跨域。

JSONP

JSONP(JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明才智开发出来,只支持get请求。

JSONP工作原理

在网页有一些标签天生具有跨域的能力,比如:img、link、iframe、script。JSONP就是利用script标签的跨域能力来发送请求的,

JSONP的使用

好麻烦,懒得搞 O(∩_∩)O

CORS

CORS(Cross Origin Resourse Sharing),跨域资源共享。CORS是官方的的跨域解决方法,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持get和post请求。跨域资源共享标准新增了一组HTTP首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。

CORS工作原理

CORS是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。

CORS的使用

在服务器端进行设置

1
2
3
response.setHeader("Access-Control-Allow-Origin","*")
//这里的*可以替换为具体的域名表示对单个域名设置跨域允许
response.setHeader(""Access-Control-Allow-Origin","http://127.0.0.1:/cors-server")

更多的相关属性设置可以查看这个文档