1,ajax介绍
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术
Ajax 核心是JavaScript和 Xml (json) :使用javascript操作异步对象XMLHttpRequest,和浏览器交换使用json数据格式
2,Ajax的优缺点
优点
1)可以不刷新页面与服务端通讯
2)允许根据用户事件来更新部分页面内容。
缺点
1)没有浏览历史不能回退
2)存在跨域问题(同源)
3)seo不友好
全局刷新和局部刷新
ajax是一种局部刷新方法
3,http协议
超文本传输协议,协议详细的规定了浏览器和万维网之间互相通信的规则
- 请求:及客户端向服务端发送的请求
发送内容即【请求报文】
- 响应:服务端在收到客户端请求后返回的响应
响应内容即响应报文
请求方式
-
GET
(主要用于查询某个数据,并不修改)向特定的资源发出请求
-
POST
(主要用于修改某个数据)向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改。(主要用于修改某个数据)
-
DELETE
(主要用于请求删除服务端数据) -
PUT
(主要用于对服务资源的数据进行修改) -
PATCH
(主要用于对服务的某个资源进行局部修改) -
PUT和PATCH区别
PUT和PATCH都是用来修改服务端某个资源的,但是PUT和PATCH修改时提交的数据是不同的,PUT将整个资源的信息提交到服务端,包括修改的,未修改的都提交到服务端,而PATCH只提交已修改的字段到服务端。而服务端对PUT请求应该是整体替换,PATCH请求只修改提交的字段。。 -
OPTION(OPTIONS请求一般是客户端向服务端判断对某个资源是否有访问权限)
返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性
-
TRACE
-
CONNECT(建立连接渠道,用于代理服务器)
-
HEAD(HEAD请求一般是用来获取某个资源的metadata信息,比如说某份报告的关键描述信息等)
前5种较为常用
4 格式与参数
请求报文:
-
行 GET (请求方式) | /s?uname = sss ( url路径) | HTTP/1.1(协议版本)
-
请求头 host: …
Cook:···········
-
空行
-
请求体 请求的数据(如果是get请求,请求体为空;如果为post请求,请求体可以不为空,GET请求数据在url路径中,而POST请求数据在请求体中)
响应报文
-
行 HTTP/1.1(协议版本) | 200(状态码) | ok(响应状态字符串)
-
响应头 con:············
content-co·········
(对响应体进行描述·)
-
空行
-
响应体 返回的内容(字符串)
5,XMLHttpRequest对象
所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject)。
XMLHttpRequest 用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
-
创建XMLHttpRequest();
-
利用new一个对象的方式创建一个对象
let xhr = new XMLHttpRequest();
6,向服务器发送请求
如需将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open() 和 send() 方法:
xhr.open("GET","ajax_info.txt",true);
xhr.send();
-
参数说明
-方法 -描述 open(method,url,asyns); 规定请求的类型、URL 以及是否异步处理请求。 method:规定请求的类型----GET/POST url:文件在服务器上的位置 asyns:规定异步(true)或者同步(false) send(); 将请求发送到服务器上,有一个参数仅限于POST请求使用
7,ie服务器请求缓存问题
当使用IE浏览器来请求服务器数据时,因为ie服务器的动态缓存问题,即刷新页面时不能及时得到刷新的响应内容
解决方法:
xhr.open('GET','http://127.0.0.1:3080/'+Date.now(),true);
//利用时间戳的唯一性给每个请求加上不同------是ie不能动态缓存
8,设置请求头
如果需要像 HTML 表单那样 POST 数据,使用 setRequestHeader() 来添加 HTTP 头。然后在 send() 方法中规定希望发送的数据:
xhr.open("POST","/try/ajax/demo_post2.php",true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send("fname=Henry&lname=Ford");
-方法 | -描述 |
---|---|
setRequestHeader(‘header’,‘value’) | 向请求添加http头,header(规定头的名称),value(规定头的值)。 |
1,application/json(JSON数据格式)
xml.setRequestHeader(“Content-type”,“application/json; charset=utf-8”);
告诉服务端消息主体是序列化后的 JSON 字符串。
2,application/x-www-form-urlencoded
xml.setRequestHeader(“Content-type”, “application/x-www-form-urlencoded; charset=utf-8”);
常见的 POST 提交数据的方式。浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据
3,multipart/form-data
xml.setRequestHeader(“Content-type”, “multipart/form-data; charset=utf-8”);
这常见的 POST 数据提交的方式。使用表单上传文件时,必须让 form 的 enctyped 等于这个值
9,服务器的响应
responseText可以获得服务器的响应数据( 获得字符串形式的响应数据)
//更改div中的数据----显示为服务器响应的数据
div.innerText=xhr.responseText;
10,onreadystatechange事件
当请求被发送到服务器时,我们需要执行一些基于响应的任务。
每当 readyState 改变时,就会触发 onreadystatechange 事件。
readyState 属性存有 XMLHttpRequest 的状态信息
-属性 | -描述 |
---|---|
onreadystatechange | 存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。 |
readyState | 存有 XMLHttpRequest 的状态。从 0 到 4 发生变化 |
0: 请求未初始化 | |
1: 服务器连接已建立 | |
2: 请求已接收 | |
3: 请求处理中 | |
4: 请求已完成,且响应已就绪 | |
status(状态码) | 200: “OK” |
404: 未找到页面 |
-
在 onreadystatechange 事件中,我们规定当服务器响应已做好被处理的准备时所执行的任务。
-
当 readyState 等于 4 且状态为 200 时,表示响应已就绪:
详细状态码可查找网络资源
11,基础ajax操作
-
服务端
//引入express核心模块 const express = require('express'); //创建应用对象 const app = express(); //创建路由规则 //request:请求报文 //response:响应报文 app.get('/index',(req,res)=>{ //设置响应头----允许跨域 res.setHeader('Access-Control-Allow-Origin','*'); res.send('HELLO AJAX') ;//响应体:响应一个‘HELLO AJAX’ }); //监听端口,启动服务 app.Listen(3080.()={ console.log('服务器启动成功·'); })
-
客户端
//获取按钮事件
const btn = document.querySelector('buttton');
//绑定事件
btn.addEventListener('click',functon(){
//创建对象
const xhr = XMLHttpRequest();
//初始化 设置请求方法和url
xhr.open('GET','http://127.0.0.1:3080/index');
//发送请求
xhr.send();
//事件绑定 处理服务端返回的结果
xhr.addEventListener('readystatechange',function(){
//readystate 是xhr对象中的属性 ,表示状态 0 1 2 3 4
//change 改变
//判断(服务器是否返回了所有结果)
if(xhr.readyState === 4){
//判断响应状态码 200 300 400 500····
//状态码在200-300之间表示正常
if(xhr.status >= 200 &&xhr.status<300){
//xhr.status--状态码
//xhr.statusText----状态字符串
//xhr.getAllResponseHeaders()---所有响应头
//xhr.response-----响应体
console.log(xhr.response);
}else{
console.log('无响应');
}
}
});
});
12ajax发送post请求
- 客户端
const div = document.querySelector('div');
div.addEventListener('mouseover', function () {
// 创建xhr对象
let xhr = new XMLHttpRequest();
// 初始化----设置请求路径和请求类型
xhr.open('POST', 'http://127.0.0.1:3080/ind');
// 发送请求并设置发送参数
xhr.send('李斌洋是一个大傻子');
//事件绑定 处理服务端返回的结果
xhr.addEventListener('readystatechange', function () {
//readystate 是xhr对象中的属性 ,表示状态 0 1 2 3 4
//change 改变
//判断(服务器是否返回了所有结果)
if (xhr.readyState === 4) {
//判断响应状态码 200 300 400 500····
//状态码在200-300之间表示正常
if (xhr.status >= 200 && xhr.status < 300) {
div.innerText = xhr.response;
}
}
});
});
- 服务端
// 设置post路由
app.post('/ind', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.send('Hello Ajax POST');
});
13,服务端请求JSON数据
服务器响应的数据一般是JSON,字符串型的,当客户端收到后一般需要将其转换为对象才能使用
- 可以使用responseType = ‘json’;来设置响应的类型
服务端
const express = require('express');
const app = express();
app.get('/index', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
let data = {
uname: 'andy'
};
// 将数据转换为字符串
res.send(JSON.stringify(data));
});
app.listen(3080, () => console.log('启动成功'));
客户端
<script>
let div = document.querySelector('div');
div.addEventListener('click', function () {
let xhr = new XMLHttpRequest();
xhr.responseType = 'json';//设置接收到的json数据转换为对象类型
xhr.open('GET', 'http://127.0.0.1:3080/index');
xhr.send();
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
let date = xhr.response;//date为对象
div.innerText = date.uname;//用.属性名的方式获得数据
}
}
});
});
</script>
14,ajax请求延迟和网络中断
当服务器出现网络延迟或者网络中断时需要给予一定的处理
- timeout
- outtime回调函数(处理网络延迟)
- onerror回调函数(处理网络中断)
服务端
const express = require('express');
const app = express();
// app.get('/', (req, res) => {
// res.setHeader('Access-Control-Allow-Origin', '*');
// });
app.get('/', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
// 设置5s候响应------模拟网络延时
setTimeout(function () {
res.send('hello ajax');
}, 5000);
});
app.listen(3080, () => console.log('启动成功'));
客户端
<script>
let div = document.querySelector('div');
div.addEventListener('click', function () {
let xhr = new XMLHttpRequest();
//若是3s还未收到,,则取消请求
xhr.timeout = 3000;
// 在控制台可以发现请求被取消----因为服务器的响应被设置了定时器5s后才返回响应
// 添加超时的回调函数----请求超时取消后返回一个内容
xhr.ontimeout = function () {
alert('网络超时');
};
// 添加网络异常的回调函数---请求网络异常后返回一个内容
xhr.onerror = function () {
alert('网络错误');
};
xhr.open('GET', 'http://127.0.0.1:3080/');
xhr.send();
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
div.innerText = xhr.response;
}
}
});
});
</script>
15,ajax取消请求
可以使用abort();方法取消正在进行请求
服务端
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
setTimeout(function () {
res.send('hello');
}, 5000);
});
app.listen(3080, () => console.log('启动成功'));
客户端
const btns = document.querySelectorAll('button');
let xhr = null;
btns[0].addEventListener('click', function () {
xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:3080/');
xhr.send();
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.ststus < 300) {
alert('响应成功');
}
}
});
// 使用abort()方法可以取消请求
btns[1].addEventListener('click', function () {
xhr.abort();
});
});
16,阻止用户疯狂请求
可以使用节流阀的方式来阻止过于频繁的请求
服务端
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
// 设置5s候响应------模拟网络延时
setTimeout(function () {
res.send('hello ajax');
}, 5000);
});
app.listen(3080, () => console.log('启动成功'));
客户端
const btns = document.querySelectorAll('button');
let xhr = null;
let flag = false;//利用节流阀来控制请求次数
btns[0].addEventListener('click', function () {
if (flag) {//当flag为true时清除请求
xhr.abort();
}
xhr = new XMLHttpRequest();
flag = true;//点击后会创建一个请求 flag为true
xhr.open('GET', 'http://127.0.0.1:3080/');
xhr.send();
xhr.addEventListener('readystatechange', function () {
if (xhr.readyState === 4) {
flag = false;//当获得响应后flag会变为false,可以重新请求了
if (xhr.status >= 200 && xhr.ststus < 300) {
alert('响应成功');
}
}
});
// 使用abort()方法可以取消请求
btns[1].addEventListener('click', function () {
xhr.abort();
});
});