目录
AJAX(Asynchronous JavaScript and XML)
序言
AJAX是通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。现在来复习一下这块内容,即使说从工作到现在一直就没有用到过,但是这块内容值得大家去学习的。
AJAX(Asynchronous JavaScript and XML)
AJAX是异步的 JavaScript 和 XML的缩写。AJAX 不是新的编程语言,而是一种使用现有标准的新方法。AJAX 是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下。
XML是可扩展标记语言(Extensible Markup Language)的缩写。XML和HTML类似,不同的是HTML中都是预定义标签,而XML中没有预定义标签,全是自定义标签。之前都是用原生的JS,后面慢慢都采用JSON对象替代了。
优点:
- 可以无需刷新页面与服务端进行通信。
- 允许你根据用户事件来更新部分页面内容。
缺点:
- 没有浏览历史,不能回退。
- 存在跨域问题。
- SEO(Search Engine Optimization)不友好。
Express框架使用
打开安装好的visual studio code(已安装nodeJs),输入命令npm init --yes初始化,
初始化后,写一个简单的js,
//1、引入express
const express = require('express');
//2、创建应用对象
const app = express();
//3、创建路由规则(request是对请求报文的封装,response是对响应报文的封装)
app.get('/',(request,response)=>{
//设置响应
response.send('HELLO EXPRESS');
});
//4、监听端口启动服务
app.listen(8000,()=>{
console.log("服务已启动,8000端口监听中... ...");
})
服务启动后,在浏览器中输入http://127.0.0.1:8000/对本地ip的8000端口发起get请求后得到如下响应,
原生AJAX
在Visual Studio Code安装Open In Default Browser插件,然后写一个html文件如下,放上一个button和块元素result
<!-- !直接出模版 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AJAX GET 请求</title>
<style>
#result{
width: 200px;
height: 100px;
border: solid 1px #90b;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result"></div>
</body>
</html>
在浏览器中打开后如下,
再写一个服务端js(server.js),/server是路径
//1、引入express
const express = require('express');
//2、创建应用对象
const app = express();
//3、创建路由规则(request是对请求报文的封装,response是对响应报文的封装)
app.get('/server',(request,response)=>{
//设置响应头,设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
//设置响应体
response.send('HELLO AJAX');
});
//4、监听端口启动服务
app.listen(8000,()=>{
console.log("服务已启动,8000端口监听中... ...");
})
输入http://127.0.0.1:8000/server访问请求后响应得到预置的响应体。
修改html文件,拿到button元素和result结果,button绑定请求事件后响应成功设置result文本信息。
<!-- !直接出模版 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AJAX GET 请求</title>
<style>
#result{
width: 200px;
height: 100px;
border: solid 1px #90b;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result"></div>
<script>
//获取button元素
const btn = document.getElementsByTagName('button')[0];
const result = document.getElementById("result");
//绑定事件
btn.onclick = function(){
//1、创建对象
const xhr = new XMLHttpRequest();
//2、初始化,设置请求方法和url
xhr.open('GET','http://127.0.0.1:8000/server');
//3、发送
xhr.send();
//4、事件绑定 处理服务端返回的结果 readystate是xhr对象中的属性,表示状态
xhr.onreadystatechange = function(){
//判断readystate状态0——(未初始化)还没有调用send方法;1——(载入)已经调用send方法,正在发送请求;2——(载入完成)send方法执行完成,已经接收到全部响应内容;3——(交互)正在解析响应内容;4——(完成)响应内容解析完成,可以在客户端调用
if(xhr.readyState === 4){
//判断响应状态码 200 404 403 401 500
//2xx成功
if(xhr.status >= 200 && xhr.status<300){
//处理结果 行 头 空行 体
// 1、响应行
// console.log(xhr.status); //状态码
// console.log(xhr.statusText); //状态字符串
// console.log(xhr.getAllResponseHeaders()); //所有响应头
// console.log(xhr.response); //响应体
// //设置result的文本
result.innerHTML = xhr.response;
}else{
}
}
}
}
</script>
</body>
</html>
最后得到的效果如下,如果需要在请求里加上参数使用?parameter=100这样的方式多个参数用&,
POST请求与GET请求类似,虽然GET请求更简单更快,但是下面几种情况应该使用POST请求:
- 无法使用缓存文件(更新服务器上的文件或数据库)。
- 向服务器发送大量数据(POST 没有数据量限制)。
- 发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠。
下面看一下JSON的案例,按下键盘任意键触发事件响应服务器的JSON数据,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JSON响应</title>
<style>
#result{
width: 200px;
height: 100px;
border: solid 1px #89b;
}
</style>
</head>
<body>
<div id = 'result'></div>
<script>
const result = document.getElementById('result');
//绑定键盘按下事件
window.onkeydown = function(){
const xhr = new XMLHttpRequest();
//设置响应体数据的类型
xhr.responseType = 'json';
xhr.open('GET','http://127.0.0.1:8000/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;
//1、手动将数据转换一下
// let data = JSON.parse(xhr.response);
// console.log(data);
// result.innerHTML = data.name;
//2、自动转换,上面设置响应数据类型
console.log(xhr.response);
result.innerHTML = xhr.response.name;
}
}
}
}
</script>
</body>
</html>
上面是响应JSON的Html文件,下面是server.js中的代码,响应一个数据集合
app.get('/json-server',(request,response)=>{
//设置响应头,设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
//响应一个数据
const data = {
name : 'my test data',
age : 23
};
let str = JSON.stringify(data);
response.send(str)
});
按下按键响应结果如下,
Nodemon
官网:https://www.npmjs.com/package/nodemon
nodemon是一种工具,可以自动检测到目录中的文件更改时通过重新启动应用程序来调试基于node.js的应用程序,毕竟上面的调试过程每次修改都需要重新重启。
按照官网安装后,可以输入nodemon server.js即可启动,如下图
后面进行修改js后,保存就会restarting。简化我们的调试。
jQuery
jQuery 是一个“写的更少,但做的更多”的轻量级 JavaScript 库。引入jQuery库可以在https://www.bootcdn.cn/中搜索该库的url进行引用,不过实际开发过程中需要考虑自己所引用的依赖是否稳定。
jQuery具体学习可以参考w3School官网上的:https://www.w3school.com.cn/jquery/jquery_animate.asp,去实现各元素实例的操作。
下面给出一个使用jQuery发送Ajax请求的例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JQuery 发送 AJAX请求</title>
<!-- html link 必须要有,告诉浏览器引入了一个样式,type="text/css"表示 类型=层次/样式-->
<link crossorigin="anonymous" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.1/css/bootstrap-grid.css">
<!-- 加上crossorigin="anonymous" 跨源属性设置 匿名——向后面这个发起请求时将不会携带当前域名下的cookies -->
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
</head>
<body>
<div class="container">
<h2 class="page-header">JQuery 发送AJAX请求</h2>
<button class="btn btn-primary">GET</button>
<button class="btn btn-danger">POST</button>
<button class="btn btn-info">通用型方法AJAX</button>
</div>
<script>
$('button').eq(0).click(function(){
//第一个参数是请求URL,第二个参数是一个对象,第三个参数是一个回调函数
$.get('http://127.0.0.1:8000/jQuery-server',{a:100,b:200}, function(data){
console.log(data)
},'json') //后面加json,表明请求返回的响应体是一个json对象
})
$('button').eq(1).click(function(){
$.post('http://127.0.0.1:8000/jQuery-server',{a:100,b:200}, function(data){
console.log(data)
})
})
$('button').eq(2).click(function(){
$.ajax({
//url,请求delay方法会因为请求超时而调用失败回调函数
url: 'http://127.0.0.1:8000/jQuery-server',
//参数
data: {a:100,b:200},
//请求类型
type: 'GET',
//响应体结果类型
dataType: 'json',
//成功的回调
success: function(data){
console.log(data);
},
//超时时间
timeout: 2000,
//失败的回调
error: function(){
console.log('请求出错了!')
},
//头信息
headers:{
c:300,
d:400
}
})
})
</script>
</body>
</html>
Axios
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
github项目链接:https://github.com/axios/axios/
API中文文档链接:http://www.axios-js.com/zh-cn/docs/
可以直接在页面上引用axios的cdn即可。
同源策略(Same Origin Policy)
同源策略,它是由Netscape提出的一个著名的安全策略。它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。
同源策略的约定是域名、协议、端口都相同。即当前网页请求另一个网页资源时必须时域名、协议、端口均相同的服务器进程资源。
只有满足同源策略的地址才可以相互通过AJAX的方式请求。
跨域(Cross Origin)
浏览器默认是有同源策略的,如果想要在某一个网页请求不同域的资源则会存在跨域问题,跨域问题的解决方案有如下几种:
- jsonp(JSON With Padding)是json的一种“使用模式”,可以让网页从别的域名获取数据。
- 设置跨域资源共享CROS(Cross-Origin Resource Sharing)响应头。
之前还说过,如果在测试过程中,例如谷歌浏览器可以在浏览器中输入chrome://flags/禁用同源策略的组件。
其他
1、AJAX请求可能会有IE缓存问题,解决方案在请求url后面加上一个时间参数。
2、AJAX请求超时/网络异常可以设置一个回调函数。
3、取消——abort函数
4、如果有重复请求,可以设置一个是否有重复请求标识,当前面一个请求还没完毕时,取消前面的重复请求,创建一个新的请求,这样可以减少服务器的压力,避免多次重复请求。
5、服务端设置响应头允许跨域后,在请求服务端时会请求两次,第一次是preflight用于验证,第二次才是真正发送的请求。参考:http://www.ruanyifeng.com/blog/2016/04/cors.html
6、可以使用fetch函数发送HTTP数据请求,它是原生js,不需要使用XMLHttpRequest对象。API文档:https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch
7、Ajax默认支持同源策略。
举个例子,html文件body中创建一个按钮,点击时触发事件,
btn.onclick = function(){
fetch('http://127.0.0.1:8000/fetch-server',{
method : 'POST',
headers :{
name:'fetch function'
},
body: 'username=admin&password=admin'
}).then(response=>{
return response.json();
}).then(response=>{
console.log(response);
});
}
总结
上面主要简单的介绍了使用AJAX向服务端发起HTTP请求,大致让大家可以了解到请求的过程是怎样的。不过这里HTTP请求的方法不止GET和POST,在官网上我们可以看到HTTP Request Methods有下面几种:
HTTP Request Method | 请求是否有主体 | 成功的响应是否有主体 | 安全(safe) | 幂等(idempotent) | 可缓存(Cacheable) | HTML 表单是否支持 |
---|---|---|---|---|---|---|
GET | 否 | 是 | 是 | 是 | 是 | 是 |
POST | 是 | 是 | 否 | 否 | Only if freshness information is included | 是 |
PUT | 是 | 否 | 否 | 是 | 否 | 否 |
DELETE | 可以有 | 可以有 | 否 | 是 | 否 | 否 |
CONNECT | 否 | 是 | 否 | 否 | 否 | 否 |
HEAD | 否 | 否 | 是 | 是 | 是 | 否 |
OPTIONS | 否 | 是 | 是 | 是 | 否 | 否 |
PATCH | 是 | 否 | 否 | 否 | 否 | 否 |
TRACE | 否 | 否 | 否 | 是 | 否 | 否 |
可以看到官网上的一些信息(这里顺便提一句为什么要去找官网上的信息,因为网上的部分信息可能根本不正确,只有官方上的知识可信度比较高,信息爆炸的时代不能瞎信别人传播的知识,需要通过自己的认知去判断。比如我们做开发,其实大部分时候都是使用的现有的框架体系去做开发,再加上一些约束,也可以说是需求给的要求去完成某个功能,自己去费劲的开发已经开源的东西可能不太可靠,可以借鉴学习。再打个比方,大伙去开发一个加密管理系统,使用的加密算法一般都得是世界公认可靠的加密算法吧,你自己想出来的算法可能没有经过很多大神们的验证检验,可靠性太低,可能使用了后会出大问题。),那么大家可以想两个问题:
1、发起HTTP请求去更新DB中的数据我是用POST还是PUT?
2、发起HTTP去删除DB中的数据我是用GET还是DELETE?
有过开发经验的可能知道,更新DB中的数据我们常使用POST,删除DB中的数据我们常使用GET。可以看到HTTP请求方法中,PUT没有响应体,我们在请求完成之后不知道结果如何,另外PUT是幂等操作(即无论多少次对同一个HTTP发起请求,它们的响应结果都是相等的),有些时候更新我们并不需要它是幂等操作,比如在更新操作里记录了操作日志,虽然对同一个东西做了相同的更新操作,但是操作记录里会有多次更新的记录。
再看看GET和DELETE虽然都是幂等的,但DELETE是不安全的。因此最常用的两种请求方式就是GET和POST,下面详细看看它两区别:
参考链接:
1、https://www.w3school.com.cn/tags/tag_doctype.asp
2、https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/GET
3、https://www.bilibili.com/video/BV1WC4y1b78y?p=10&spm_id_from=pageDriver