1.AJAX简介
1.1 AJAX是什么?
AJAX全称为Asynchronous JavaScript And XML,就是异步的JS和XML。
通过AJAX可以向浏览器发送异步的请求,可以无刷新的获取数据。AJAX不是编程语言,它是现有的标准组合在一起的新方法。
1.2 XML简介
XML可扩展标记语言。XML被设计用来传输和存储数据。
XML和HTML类似,但XML中的标签都是自定义标签,没有预定义标签。
XML表示数据:
<student>
<name>zhangsan</name>
<age>18</age>
<gender>men</gender>
</student>
Ajax最初是使用xml进行数据传输的媒介的,但由于xml书写起来有点麻烦,之后就设计出了JSON代替了XML作为数据传输的媒介。
1.3 JSON简介
JSON(JavaScript Object Notation,JS标记对象)是一种轻量级数据交换格式。
JSON是通过键值对的形式进行数据的保存的,JSON的写法和JS中的对象写法大同小异。
{
"key1":"value",//可以是字符串
"key2":-123.21,//可以是数字
"key3":{
"name":"zhangsan"
"age":"21"
}//可以是json对象
"key4":[1,2,3,4]//可以是数字数组
"key5":["a","b","c"]//可以是字符串数组
"key6":[{
"name":"a"
"age":"12"
},{
"name":"b"
"age":"12"
},{
"name":"c"
"age":"13"
}]//可以json对象数组
"key7":null
}
1.4 Ajax的特点
1.优点
- 无刷新页面与服务器进行交互
- 可以通过用户数据来更新部分页面内容
2.缺点
- 没有浏览历史,不能回退
- 存在跨域问题(同源)
- SEO不友好
跨域问题:协议+域名+端口号,如果请求方和所请求资源的目标方上面三个都相同就是同源,如果不一样那么就是跨域
SEO:earch engine optimization的缩写,翻译过来就是“搜索引擎优化”,利用搜索引擎优化规则提高网站在有关搜索引擎内的自然排名的方式
1.5 HTTP协议
什么事HTTP协议?
HTTP 协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写。是用于从万维网服务器传输超文本到本地浏览器的传送协议;
HTTP基于TCP/IP通信协议来传递数据;
2. 开始上手Ajax
2.1 准备工作
1.安装node.js
node.js是一个开源而且跨平台的JavaScript运行时环境,可以把它当做为JavaScript的解释器。
在官网上下载安装node.js,安装完成后在cmd使用node -v
来判断node.js是安装好。
2.express服务器框架
这里为了测试练习ajax,我们需要一个服务器端,这里我们使用express服务器框架来运行我们的服务器。
基本操作:
在你的项目下打开终端,
之后输入npm init --yse
npm是一个包管理工具
这里做了一个初始化操作,会在你打开终端的文件夹中创建package.json文件
之后输入npm i express安装express框架
在文件夹下建立js文件输入以下代码:
//1.引入express
const express = require('express');
//2.创建应用对象
const app =express();
//3.创建路由规则
//request是对请求报文的封装,response是对响应报文的封装。
app.get('/',(request,response)=>{
//处理跨域问题(后面会讲跨域问题,这里先写上)
response.setHeader('Access-Control-Allow-Origin','*');
response.setHeader('Access-Control-Allow-Headers','*');
response.setHeader('Access-Control-Allow-Method','*');
//设置响应
response.send('HELLO EXPRESS');
});
//4.监听端口启动服务
app.listen(8000,()=>{
console.log("服务已经启动,8000端口监听");
})
然后使用终端打开
输入node 创建的js文件名
就可以打开服务器
按下ctrl+C可以结束服务器。
输入127.0.0.1:8000
访问服务器。
Nodeman工具:
可以自动检测到服务器的文件有所更改并且自动进行重启。
在终端中使用npm install -g nodemon
进行安装,之后使用nodemon js文件
进行服务器的启动。
2.2 XMLHttpRequest对象
Ajax中最核心的技术就是XMLHttpRequest,它是一个具有应用程序接口的JavaScript对象,能够使用超文本传输协议(HTTP)连接一个服务器。
使用XMLHttpRequest对象
1.初始化XMLHttpRequest对象
var xhr = new XMLHttpRequest
如果是ie浏览器则是针对两个不同版本
var xhr = new ActiveXObject("Msxml2.XMLHTTP");
和
var xhr = new ActiveXObject("Microsoft.XMLHTTP");
在不同的浏览器中获取XMLHttpRequest对象或者ie的ActiveX对象:
var getxhr = function(){
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
try{
xhr = ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
try{
xhr = ActiveXObject("Microsoft.XMLHTTP");
}catch(e){}
}
}
return xhr;
}
2.XMLHttpRequest对象的常用方法
- open()方法
open("method","URL"[,asyncFlag[,"username[,"password"]"]])
method:指定请求类型
URL:指定请求地址。
asyncFlag:可选参数,用于指定请求方式,异步请求为true,同步为false
username:可选参数,用于指定请求用户名,没有时可以省略。
password:可选参数,用于指定请求密码,没有时可以省略。
xhr.open("GET","index.html",true)
- send()方法
向服务器发送请求。
如果为异步该方法立刻返回,同步的话则需要等到接收到响应为止。
send(content);
content可以是DOM对象的实例、输入流或字符串,如果没有参数传输可以设置为null。 - setRequestHeader()方法
为请求的HTTP头设置值。
setRequestHeader("header","value")
需要在调用open方法后才能使用。
header:用于指定HTTP头。
value:用于为指定的HTTP头设置的值。 - abort()方法
停止或放弃当前异步的请求。
abort()
- getResponseHeader()方法
以字符串的形式返回指定的HTTP头信息。
getResponseHeader("headerLabel")
headerLabel:用于指定的HTTP头,包括Sever、Content-Type和Date等。 - getAllResponseHeaders()
以字符串形式返回完整的HTTP头信息。包括Server、Date、Content-Type和Content-Length。
getAllResponseHeaders()
3.XMLHttpRequest对象的常见属性
- onreadystatechange属性
用于指定状态改变时所触发的事件处理器。
xhr.onreadystatechange = function(){
console.log("hello!");
}
- readyState属性
表示了获取请求的请求状态,总共有五个请求值。
0:未初始化。
1:正在加载。表示open方法已经调用完毕
2:已加载。表示send方法调用完毕
3:交互中。表示服务端返回了部分结果(正在传输结果,还没有传输完毕)
4:完成。表示服务端返回了所有结果。 - responseText属性
用于获取服务器的响应,为字符串。 - responseXML属性
用于获取服务器的响应,为XML。这个对象可以解析为一个DOM对象。 - status属性
返回HTTP服务器的状态码。
常见状态码:
1xx :信息响应类,表示接收到请求并且继续处理
2xx :处理成功响应类,表示动作被成功接收、理解和响应
3xx :重定向响应类,为了完成指定的动作,必须进行进一步处理
4xx :客户端错误,客户端请求包含语法错误或者是不能被服务端理解
5xx :服务端错误,服务器不能正确执行一个有效的请求
----------------------------------------------------------
200 OK :请求已经被正确处理并响应。
301 Move Permanently :永久重定向。
302 Move Temporarily :临时重定向。
400 Bad Request :服务器不能理解请求。
401 Authentication Required :需要验证用户身份。
403 Forbidden :禁止访问资源。
404 Not Found :资源没有找到。
405 Method Not Allowed :在资源上使用了错误的方法,如应该用 POST,却用了 PUT。
408 Request Timeout :请求超时。
500 Internal Server Error :服务器内部错误。
501 Method Not Implemented :请求方法无效,如可能将 GET 写成 Get。
502 Bad Gateway :网关或者代理从上游服务器收到了错误的响应。
503 Service Unavailable :服务暂时不可用,可稍后尝试。
504 Gateway Timeout :网关或代理向上游服务器请求超时。
- statusText属性
放回HTTP状态码对应的文本,如OK或Not Found等。
2.3 与服务器进行通信
1 发送请求
无论是发送get请求还是post请求其流程都是差不多的。
一般分为四个步骤:
- 初始化XMLHttpRequest对象
xhr = false;
if(window.XMLHttpRequest){//非ie
xhr = new XMLHttpRequest();
}else if(window.ActiveXObject){//ie
try{
xhr = new ActiveXObject("XsXML2.XMLHTTP");
}catch(e){
try{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}catch(e){
}
}
}else{
xhr=false;
}
- 为XMLHttpRequest对象的回调函数。
xhr = function(){
//操作
}
- 创建与与服务器的连接
xhr.open('GET','URL');//采用异步的方式发送get类型的请求
xhr.open('POST','URL');//采用异步的方式发送post类型的请求
在指定url参数时,可以在后面加上时间戳,防止因浏览器的缓存,导致数据不能拿到最新结果。
String url = "index.html?nocache="+new Date().getTime();
- 向服务器发送请求
xhr.send(content);
如果是post发送请求,还要在发送请求加上正确的请求头。
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
发送的请求头可以自定义,xhr.setRequestHeader("键","值");
但是自定义会有安全机制导致报错,在服务器中加上这句response.setHeader('Access-Control-Allow-Headers','*');
(之前已经加了*号可以改成自己想要选择通过的请求头名),之后浏览器会再发送一个options的请求来效验这个头信息可不可以用,如果没有得到浏览器的响应,那么这个请求还是会失败。
2.处理服务器响应
我们一般通过XMLHttpRequest对象的onreadystatechange属性来指定一个回调函数,用于处理服务器响应。首先需要判断服务器的请求状态,还要判断服务器是否对请求响应成功,如果成功则对服务器发送的响应进行处理。(为了方便学习我们可以把app.get改为app.all可以接受任意类型的数据)
- 处理字符串响应
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status<300){//认为2xx的响应都是成功的。
console.log(xhr.responseText);
}
}
}
- 处理xml响应
图书信息的XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<mr>
<books>
<book>
<title>java基础</title>
<publisher>清华大学</publisher>
</book>
<book>
<title>javascript权威指南</title>
<publisher>机械工业出版社</publisher>
</book>
</books>
</mr>
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status >=200 && xhr.status<300){
var XMLdoc = xhr.responseXML;
for(i=0;i<XMLdoc.getElementsByTagName("book").length;i++){
var book = XMLdoc.getElementsBydTagName("book").item(i);
console.log("书名:"+book.getElementlsByTagName('title')[0].firstChild.data);
console.log("出版社:"+book.getElementlsByTagName('title')[0].firstChild.data);
}
}
}
}
- 处理JSON响应
对对象进行字符串转化的方法:
let data = {
name:zhangsan,
sex:man
}
let stringDate = JSON.stringify(data);
对JSON转化为对象的方法:
let stringData = "{name:zhangsan,sex:man}"
let data = JSON.parse(stringData)
浏览器处理服务器发送的响应数据时可以设置好XMLHttpRequest对象的responseType属性,将responseType属性设置为json:
xhr.responseType = 'json'
之后的xhr.response就可以直接转化为JSON的对象。
2.4 Ajax的常见问题
1.请求重复问题
使用xhr.abort()
取消当前ajax请求。
当我们设置点击按钮发送ajax请求时,如果用户不停的点击发送ajxa请求的按钮时,会发送重复的ajax请求,为了减少服务器的压力,我们可以将重复的请求取消。
通过设置参数的方式
var sendbtn = document.getElementById("sendbtn");
var isSending = false;
var xhr;
sendbtn.onclick = function(){
if(isSending) xhr.abort();
isSending = true;
xhr = new XMLHttpReponse();
xhr.open("GET","url");
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readystate == 4){
isSending = false;
}
}
}
pending状态
一个已经产生的信号,但是还没有传递给任何进程,此时该信号的状态就称为未决态即pending态。
2.IE缓存问题
这里之前讲过,IE缓存问题,IE浏览器会将ajax发送的数据进行缓存,下次ajax发送数据是IE浏览器会引用自己本地的缓存,导致数据不会进行更新。
需要通过在请求中添加一个时间戳来进行处理。
xhr.open(“GET”,’http://127.0.0.1:8000/?t=’+Date.now())
3.请求超时控制和网络异常处理
设置一下服务端延迟发送数据
app.get('/testing2',(request,response)=>{
setHeader(response);
response.contentType="text/xml";
setTimeout(()=>{
response.send("延迟2s");
},2000);
})
//超时设置1s
xhr.timeout = 1000;
//超时调用ontimeout函数
xhr.ontimeout = function(){
alert("网络连接超时!");
}
2.5 axios的使用
1.使用axios函数发送请求
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。axios的本质就是对原生XMLHttpRequest的封装。
首先需要script标签将axios标签引入,可以在https://www.bootcdn.cn/中找ajax项目进行复制。
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.1.3/axios.js"></script>
在服务器端写入:
app.all('/axiostest1',(request,response)=>{
setHeader(response);
response.send('HELLO,AXIOS!');
})
axios(config)
// 发起一个post请求
axios({
method: 'post',//发送get请求的话,就将post改为get
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
axios.get(‘url’,config)
发送get请求axios.get('url',config)
这里的config是一个对象用于配置请求报文中的请求行,请求头等。
getbtn.onclick = function(){
axios.get('http://127.0.0.1:8000/axiostest1',{
params: {//url后面加的请求参数
username:'zj'
},
headers:{//请求头设置
name:'zj'
}}).then(value => {
console.log(value);
})//会将响应封装成一个一个对象,这里的value就是响应对象
}
为了方便url的写法,可以设置baseURL对url进行简化:
axios.defaults.baseURL = 'http://127.0.0.1:8000'
axios.get('/axiostest1',config);
axios.post(‘url’,data,config)
发送post请求axios.post('url',data,config)
data是请求体数据对象,config是配置对象。
axios.post('/axiostest1',{//请求体数据
username:'zhangsan'
},{
params:{//url后面加的请求参数
id:200,
pass:123
},
headers:{//请求头参数
aa:'abc'
}
}).then(value=>{
console.log(value);
});
2.使用fetch函数发送请求
Promise<Response> fetch(input[,init]);
input为一个URL字符串,也可以是一个request对象
init就是一个配置选项可以选的参数有:
method:如get、post等
haeder:请求头信息。
body:请求体信息。
等。。。
fetch('http://127.0.0.1:8000/fetchtest?vip=100',{
method:'POST',
header:{
name:'zhangsan'
}
body:'username=zhangsan&password=admin'
}).then(response = >{
console.log(response);
});
如果想要了解axios更多可以到https://www.axios-http.cn/去查看。
3.AJAX跨域问题
3.1 同源策略
同源:协议、域名和端口号必须完全相同。
跨域:协议、域名和端口号,只要有一个不同,那么就是跨域。
ajax遵循同源策略。
如果跨域使用ajax请求会导致ajax的跨域问题。
3.2 如何解决跨域问题
JSONP
网页的一些标签有着跨域的功能,JSONP就是使用script标签来实现跨域的,但只支持GET请求。
JSONP的实现:
例:
服务器端
app.get('/testKY',(request,response)=>{
response.send("console.log('你好跨域!')");
})
浏览器端
var script = document.createElement("script");//创建一个script标签
script.src = "http://127.0.0.1:8000/testKY";//设置src,src为想要进行访问的值
document.body.appendChild(script);//将script标签添加到文档流中
CORS
全称Cross-Origin Resource Sharing,跨域资源共享。是官方跨域解决方案,浏览器端不需要进行任何操作,只要服务器进行处理即可。通过设置响应头的方式,告诉浏览器允许跨域。
服务器通过设置响应头,来实现跨域。
//设置所有的域名可跨域访问,*可以改为自己想要跨域的域名
response.setHeader("Access-Control-Allow-Origin",'*')
//设置所有的请求头可以跨域访问,*可以改为自己想要跨域的请求头
response.setHeader("Access-Control-Allow-Headers",'*')
//设置所有的请求方式可以跨域访问,*可以设置自己想要跨域的请求方式
response.setHeader("Access-Control-Allow-Method",'*')
详细可以参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS
4.练习
这里我写了一些练习题,自己可以去练习练习。
练习一:点击按钮发送get与post请求,将返回的http响应包中的一些信息显示在网页之中。
练习二:点击按钮发送带有自定义头信息的post请求,将返回的http响应包中的一些信息显示在网页之中。
练习三:服务器发送字符串。分别使用get与post对服务器请求,返回的http响应包使用responseText来显示信息。
练习四:服务器发送XML。分别使用get与post对服务器请求,返回的http响应包使用responseXML来显示信息。
练习五:一个注册界面,要求输入用户名是异步的判断用户名是否存在,点击注册时防止重复发送ajax。
练习六:使用JSONP的方式,来实现练习五。
练习七:对XMLHttpRequest对象封装。