AJAX 学习笔记
  1. 原生ajax
  2. 服务端Node.js
  3. jQuery
  4. Axios

案例

express框架基础介绍

通过require引入

1
const express = require('express');

服务端node.js程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const { response } = require('express');
const express = require('express');

const app = express();

app.get('/server',(request,response)=>{
//设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');

response.send('Hello Ajax');
})

app.listen(8000,()=>{
console.log("服务已启动");

})

原生ajax

通过 创建 XMLHttpRequest()对象创建

1
const xhr = new XMLHttpRequest();

创建之后, 需要开启, 然后发送请求

1
2
3
xhr.open('GET','http://127.0.0.1:8000/server');
//发送
xhr.send();

想要处理服务端返回的结果, 要绑定事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 事件绑定, 处理服务端返回的结果
xhr.onreadystatechange = function(){
if(xhr.readyState===4){
//202 404 403 401 500

if(xhr.status>=200 &&xhr.status<300){
//处理结果

console.log(xhr.status);
console.log(xhr.statusText);
console.log(xhr.getResponseHeader);
console.log(xhr.getAllResponseHeaders);
console.log(xhr.response);


}
}
}

Ajax设置请求参数

正常设置请求参数, 就是放在请求url后面

1
xhr.open('GET','http://127.0.0.1:8000/server?a=100&b=200&c=300');

发送post请求

open的时候把参数设置为post

1
xhr.open('POST','http://localhost:8000/server');

服务端开启接受就可以

1
2
3
4
5
app.post('/server',(request,response)=>{
response.setHeader('Access-Control-Allow-Origin','*');

response.send('Hello Ajax POST');
})

POST请求设置请求体

需要在send()里面设置

1
xhr.send('a=100&b=200&c=300');

设置请求头信息

使用setRequestHeader()方法

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

也可以自定义

1
xhr.setRequestHeader('name','123456');

但是需要服务端设置

1
response.setHeader('Axess0-Control-Allow_Headers','*');

但是因为还会发一个OPTION请求, 所以服务端还需要接受OPTION请求才行

将接收方法改成all

1
2
3
4
5
app.all('/server',(request,response)=>{
response.setHeader('Access-Control-Allow-Origin','*');
response.setHeader('Axess0-Control-Allow_Headers','*');
response.send('Hello Ajax POST');
})

服务端响应JSON

使用JSON

1
2
3
4
5
6
const data ={
name: 'klen'
};

let str = JSON.stringify(data);
response.send(str);

前端解析也是使用JSON中的parse()方法

1
2
let data = JSON.parse(xhr.response);
console.log(data);

以上是手动转换json对象, 也可以开启自动转换

1
xhr.responseType = 'json';

这样前段直接获取就好了

1
result.innerHTML = xhr.response.name;

NodeMon自动重启工具

安装nodemon

1
npm install =g nodemon

使用nodemon启动服务器文件

1
nodemon server.js

请求超时和网络异常处理

服务端可以设置延时响应:

1
2
3
4
5
6
7
app.get('/delay',(request,response)=>{
//设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
setTimeout(()=>{
response.send('延时响应');
},3000);
});

客户端可以设置超时时间

如果一定时间内没有返回结果, 请求就取消

1
xhr.timeout = 200;

也可以加回调函数

1
2
3
xhr.ontimeout = function(){
alert("网络异常");
}

网络异常也可以设置回调

1
2
3
xhr.onerror = function(){
alert("你的网络出了一些问题");
}

手动取消请求

调用abort方法

1
2
3
4
cancel.onclick = function(){
xhr = new XMLHttpRequest();
xhr.abort();
}

请求重复发送问题

可以判断请求是否正在发送, 如果正在发送, 取消当前正在发送到请求, 重新发送一样的请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let xhr = null;
let isSending = false;//是否正在发送ajax请求
send.onclick = function(){
//如果正在发送, 取消该重复请求, 重新发送
if(isSending){
xhr.abort();
}
xhr = new XMLHttpRequest();
//修改标识变量值
isSending = true;
xhr.open('get','http://localhost:8000/delay')
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
isSending = false;
}
}
}

jQuery 使用Ajax

BootCDN

使用bootcdn引入在线jQuery库

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

然后使$.get()发送get类型的ajax请求

1
2
3
4
5
$('button').eq(0).click(function(){
$.get('http://localhost:8000/jquery-server',{a:100,b:200},function(data){
console.log(data);
});
});

$.post()请求也是同理,

$.get()$.post()里面还可以传递第四个参数, 'json', 代表讲响应内容转换为json

1
2
3
4
5
$('button').eq(0).click(function(){
$.get('http://localhost:8000/jquery-server',{a:100,b:200},function(data){
console.log(data);
},'json');
});

这样当服务端发送json数据都时候就可以自动转换成对象

1
2
3
//server.js
const data = {name:'klen'};
response.send(JSON.stringify(data));

通用方法

$.ajax 是个jQuery通用的发送ajax的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$('button').eq(2).click(function(){
$.ajax({
url: 'http://localhost:8000/jquery-server',
//请求类型
type: 'post',
//参数
data: {a:100,b:200},
//响应体结果设置
dataType: 'json',
//成功的回调
success: function(data){
console.log(data);
}
});
});

还有很多其他参数, 比如失败回调函数error:, 可以处理包括超时, 网络异常等问题. 还有header:设置请求头

Axios

引入js包

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

GET

使用axios.get( url[, config])发送get请求, 里面一般封装两个参数, 请求url和请求参数对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//配置baseURL
axios.defaults.baseURL = 'http://localhost:8000';

btn[0].onclick = function () {
//get请求
axios.get('/axios-server',{
params:{
id : 100,
vip: 7
},
headers:{
name: 'atguigu',
age:20
}
}).then(value => {
console.log(value);
});
}

可以使用axios.defaults.baseURL配置根地址, 这样方便书写

不同于jQuery的是, 处理返回响应axios不是使用success回调函数, 而是.then, 基于promise

value里面封装了包括请求信息, 头信息, 响应数据等等.

服务端的JSON数据自动转换成了对象.

POST

使用axios.post( url[, data[, config]])发送post请求, 有三个参数, 第二的参数是数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
axios.post('/axios-server', {
username: 'admin',
password: 'admin'
}, {
params: {
id: 200,
vip: 9
},
headers: {
name: 'atguigu',
age: 20
},

});

通用请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
axios({
url: '/axios-server',
method: 'post',
params:{
vip:10,
level:30,

},
headers:{
a:100,
b:200
},
data:{
username:'admin',
password:'admin'
}

}).then(value =>{
console.log(value);
console.log(value.status);
console.log(value.statusText);
console.log(value.headers);
console.log(value.data);
});

fetch()函数

用于发起获取资源的请求, 返回结果是一个promise, 在请求响应后被解析传回response对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
btn.onclick = function(){
fetch('http://localhost:8000/fetch-server?vip=10',{
method:'POSt',
headers:{
name: 'klen'
},
body: 'username=admin&password=admin'
}).then(response => {
// return response.text();
return response.json();

}).then(response => {
console.log(response);
});
}

跨域

违背同源策略就是跨域

同源策略

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

同源: 协议, 域名, 端口号, 必须完全相同

AJAX默认遵循同源策略

服务器的增加, 就容易形成跨域

jsonp

原理

借助script标签实现跨域, 因为script标签本身就具备跨域特性, 只支持get请求

如果在客户端使用<script> 对服务器发送请求

1
<script src="localhost:8000/jsonp-server"></script>

而服务端直接返回的是字符串形式的代码

1
response.send('console.log(hello)');

这样字符串里面的代码会被返回且执行

服务器返回代码, 也可以调用客户端中的函数,

1
2
3
4
5
const data = {
name:"klen"
}
const str = JSON.stringify(data);
response.end(`handle(${str})`); //使用 end() 响应就不会发送特殊响应头, ``中使用${}可以传参

原生jsonp

在客户端创建一个handle函数

1
2
3
4
5
//handle函数
function handle(data){
input.style.border = "solid 1px #f00";
p.innerHTML = data.msg;
}

然后为<input>绑定事件

使用创建script的方法发送请求

1
2
3
4
5
6
7
8
9
10
11
const input = document.querySelector('input');
//绑定事件
input.onblur = function(){
//获取用户的输入值
let username = this.value;
//向服务端发送请求, 检测用户名是否存在
//创建一个script标签
const script = document.createElement('script');
script.src = 'http://localhost:8000/check-username';
document.body.appendChild(script);
}

而服务端调用客户端函数

1
2
3
4
5
6
7
8
9
10
//jsonp server 检测服务是否存在
app.all('/check-username',(request,response)=>{

const data = {
exist: 1,
msg: 'username already exist'
}
let str = JSON.stringify(data);
response.end(`handle(${str})`);
});

jQuery 发送 jsonp

callback=?为必须参数

1
2
3
4
5
6
7
8
9
10
$('button').eq(0).click(function(){
$.getJSON('http://localhost:8000/jquery-jsonp-server?callback=?',function(data){
$('#result').html(`
名称: ${data.name}<br>
city: ${data.city}

`)

})
})

服务端:

1
2
3
4
5
6
7
8
9
10
11
//jsonp jquery 检测服务是否存在
app.all('/jquery-jsonp-server',(request,response)=>{

const data = {
name: 'klen',
city: ['Beijing','Shanghai','Guangzhou']
}
let str = JSON.stringify(data);
let cb = request.query.callback;
response.end(`${cb}(${str})`);
});

CORS

Cross-Origin-Recource-Sharing

官方的跨域解决方案

不用再客户端做任何特殊操作, 全部在服务区中进行处理, 设置响应头就可以

支持get, post请求

服务端设置响应头:

1
2
3
response.setHeader('Access-Control-Allow-Origin',"*");
response.setHeader('Access-Control-Allow-Headers',"*");
response.setHeader('Access-Control-Allow-Method',"*");

还有很多其他响应头可以设置

Author: klenq
Link: https://klenq.github.io/2021/11/14/Ajax学习笔记/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.