持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第31天,点击查看活动详情
原生AJAX
AJAX简介
- AJAX即Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
- AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
- 通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势:==无刷新获取数据==,即在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
- AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
- 最开始AJAX进行数据交换时所使用的格式就是XML,服务器给客户端浏览器返回结果时返回的就是XML格式的字符串,现在已经被JSON取代了。
- XML:可扩展标记语言。XML被设计用来传输和存储数据,而HTML用来呈现数据。XML和HTML类似,不同的是HTML中都是预定义标签,而XML中没有预定义标签,全都是自定义标签,用来表示一些数据。
AJAX的特点
AJAX的优点:
- 可以无需刷新页面而与服务器端进行通信。
- 允许你根据用户事件来更新部分页面内容。
AJAX的缺点:
-
没有浏览历史,不能回退。
-
存在跨域问题(同源)。
-
对SEO优化和爬虫不友好。
AJAX请求状态
==XMLHttpRequest.readyState== 属性返回一个 XMLHttpRequest 代理当前所处的状态。一个 XHR 代理总是处于下列状态中的一个: 0:表示XMLHttpRequest实例已经生成,但是open()方法还没有被调用。 1:表示send()方法还没有被调用,仍然可以使用setRequestHeader(),设定HTTP请求的头信息。 2:表示send()方法已经执行,并且头信息和状态码已经收到。 3:表示正在接收服务器传来的body部分的数据。 4:表示服务器数据已经完全接收,或者本次接收已经失败了。
服务器server.js搭建
1.安装Node.js
2.安装express(服务端框架)
2.1初始化环境npm init --yes
2.2下载express包npm i express
3.编写服务器js代码
//server.js:
//1. 引入express
const express = require('express');
//2. 创建应用对象
const app = express();
//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/get-server', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
//设置响应体
response.send('HELLO GET');
});
app.post('/post-server', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
//设置响应体
response.send('HELLO POST');
});
app.all('/json-server', (request, response) => {
// 设置响应头, 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
// 设置响应头, 设置允许自定义头信息
response.setHeader('Access-Control-Allow-Headers', '*');
// 响应一个数据
const data = {
name: 'zag666'
};
// 对 对象 进行 字符串 转换
let str = JSON.stringify(data)
// 设置响应体
response.send(str);
});
4. 监听端口启动服务
app.listen(8000, () => {
console.log("服务已经启动, 8000 端口监听中....");
});
4.运行server.js:node server.js
5.另外还可以安装nodemon自动重启工具(文件内容有修改自动重新启动服务):npm install -g nodemon;启动:ndoemon server.js
AJAX的使用
1.GET、POST
1)创建XMLHttpRequest对象
XMLHttpRequest(XHR)对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。XMLHttpRequest 在 AJAX编程中被大量使用。
var xhr=new XMLHttpRequest();
2)设置请求信息
xhr.open(method,url);
e.g.: xhr.open('GET','http://127.0.0.1:8000/json-server');
xhr.open('POST', 'http://127.0.0.1:8000/server');
可以设置请求头,一般不设置:xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
3)发送请求
xhr.send()//get请求不传body参数
xhr.send('a=100&b=200&c=300');post请求传参
4)接收响应
//xhr.responseXML接收xml格式的响应数据
//xhr.responseText接收文本格式的响应数据
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;
}
}
}
2.JSON
//json.html:
<body>
<div id="result"></div>
<script>
const result = document.getElementById('result');
// 绑定键盘按下事件
window.onkeydown = function(){
// 发送请求
const xhr = new XMLHttpRequest();
// *2*.(自动转换) 设置响应体数据的类型(自动转换)
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);
// 1. 手动对数据转化 (字符串再转换成json)
// let data = JSON.parse(xhr.response); //转换成json
// result.innerHTML = data.name;
// *2*. (自动转换)自动转换(自动转换)
result.innerHTML = xhr.response.name; //已经自动变成json
}
}
}
}
</script>
</body>
3.重复请求问题、手动取消请求、超时和网络异常
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>重复请求问题</title>
<style>
#result{
width:200px;
height:100px;
border:solid 1px #90b;
}
</style>
</head>
<body>
<div id="result"></div>
<button>点击发送(重复请求问题)</button>
<button>点击发送(手动取消请求)</button>
<button>点击发送(超时和网络异常)</button>
<script>
//获取元素对象
const btns = document.querySelectorAll('button');
const result = document.querySelector('#result');
let x = null;
let isSending = false; // 是否正在发送AJAX请求
//1.重复请求问题
btns[0].onclick = function(){
if(isSending) x.abort();// 如果正在发送, 则取消该请求, 创建一个新的请求
x = new XMLHttpRequest();
isSending = true;
x.open("GET",'http://127.0.0.1:8000/delay');
x.send();
x.onreadystatechange = function(){
if(x.readyState === 4){
//修改标识变量
isSending = false;
}
}
}
//2.手动取消请求
btns[1].onclick = function(){
x = new XMLHttpRequest();
x.abort();
console.log(x);
}
//3.超时和网络异常
btns[2].onclick = function(){
const xhr = new XMLHttpRequest();
//超时设置 2s 设置
xhr.timeout = 2000;
//超时回调
xhr.ontimeout = function(){
alert("网络异常, 请稍后重试!!");
}
//网络异常回调
xhr.onerror = function(){
alert("你的网络似乎出了一些问题!");
}
xhr.open("GET",'http://127.0.0.1:8000/delay');
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status< 300){
result.innerHTML = xhr.response;
}
}
}
}
</script>
</body>
</html>
==具体使用案例==可参考:这个
IE缓存问题
问题: 在一些浏览器中(IE),由于缓存机制的存在,ajax只会发送的第一次请求,剩余多次请求不会在发送给浏览器而是直接加载缓存中的数据。
解决方式: 浏览器的缓存是根据url地址来记录的,所以我们只需要修改url地址加一个唯一时间戳即可避免缓存问题
xhr.open("get","/testAJAX?t="+Date.now());
HTTP
HTTP请求响应过程: 前后浏览器端向服务器发送HTTP 请求(请求报文),后台服务器接收到请求后处理请求, 向浏览器端返回HTTP响应(响应报文),浏览器端接收到响应, 解析显示响应体。
一般http请求 与 ajax请求的区别
- ajax请求 是一种特别的 http请求。
- 对服务器端来说, 没有任何区别, 区别在浏览器端。
- 浏览器端发请求: 只有XHR 或fetch 发出的才是ajax 请求, 其它所有的都是非ajax 请求。
- 浏览器端接收到响应。 (1) 一般请求: 浏览器一般会直接显示响应体数据, 也就是我们常说的刷新/跳转页面。 (2) ajax请求: 浏览器不会对界面进行任何更新操作, 只是调用监视的回调函数并传入响应相关数据。
请求报文
行 POST /s?ie=utf-8 HTTP/1.1
头 Host: atguigu.com
Cookie: name=guigu
Content-type: application/x-www-form-urlencoded
User-Agent: chrome 83
空行
体 username=admin&password=admin
响应报文
行 HTTP/1.1 200 OK
头 Content-Type: text/html;charset=utf-8
Content-length: 2048
Content-encoding: gzip
空行
体 <html>
<head>
</head>
<body>
<h1>abc</h1>
</body>
</html>
jQuery中的AJAX
GET请求
$.get(url, [data], [callback], [type])
url:请求的URL 地址 data:请求携带的参数 callback:载入成功时回调函数 type:设置返回内容格式,xml, html, script, json, text, _default
POST请求
$.post(url, [data], [callback], [type])
url:请求的URL 地址 data:请求携带的参数 callback:载入成功时回调函数 type:设置返回内容格式,xml, html, script, json, text, _default
AJAX
$.ajax({
// url
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
}
})
跨域
同源策略
- 同源策略(Same-Origin Policy)最早由Netscape 公司提出,是浏览器的一种安全策略。
- 同源: 协议、域名、端口号必须完全相同。
- 跨域: 违背同源策略就是跨域。
如何解决跨域
1.JSONP
- JSONP 是什么 JSONP(JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明才智开发出来,只支持get 请求。
- JSONP 怎么工作的? 在网页有一些标签天生具有跨域能力,比如:img link iframe script。 JSONP 就是利用script 标签的跨域能力来发送请求的。
- JSONP 的使用:
1.动态的创建一个script标签
var script=document.createElement("script");
2.设置script的src,设置回调函数
script.src = "http://localhost:3000/testAJAX?callback=abc";
function abc(data) {
alert(data.name);
};
3.将script添加到body中
document.body.appendChild(script);
4.服务器中路由的处理
router.get("/testAJAX" , function (req , res) {
console.log("收到请求");
var callback = req.query.callback;
var obj = {
name:"孙悟空",
age:18
}
res.send(callback+"("+JSON.stringify(obj)+")");
});
- JQuery 中的JSONP
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button id="btn">按钮</button>
<ul id="list"></ul>
<script type="text/javascript" src="./jquery-1.12.3.js"></script>
<script type="text/javascript">
window.onload = function () {
var btn = document.getElementById('btn')
btn.onclick = function () {
$.getJSON("http://api.douban.com/v2/movie/in_theaters?callback=?",function(data) {
console.log(data);
//获取所有的电影的条目
var subjects = data.subjects;
//遍历电影条目
for(var i=0 ; i<subjects.length ; i++){
$("#list").append("<li>"+
subjects[i].title+"<br />"+
"<img src=\""+subjects[i].images.large+"\" >"+
"</li>");
}
});
}
}
</script>
</body>
</html>
2.CORS
- CORS 是什么? CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS 是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持get 和post 请求。跨域资源共享标准新增了一组HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源
- CORS 怎么工作的? CORS 是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。
- CORS 的使用 主要是服务器端的设置:
router.get("/testAJAX" , function (req , res) {
//通过res 来设置响应头,来允许跨域请求
//res.set("Access-Control-Allow-Origin","http://127.0.0.1:3000");
res.set("Access-Control-Allow-Origin","*");
res.send("testAJAX 返回的响应");
});