本篇来讲关于Ajax的内容,当然还有小伙伴可能不知道该怎么读 "Ajax",它读 "阿贾克斯" ,当然了读法可能因人而异,下面来进入正题,先来了解一下什么是Ajax?
Ajax 是什么?
Ajax 是 Asynchronous Javascript And XML 的缩写,不少初识的人以为是一门新的语言或技术,其实不然,它是异步的 Javascript 和 XML技术,是由 Javascript 、 XML 、DOM、CSS等多种已有技术合成的一种浏览端技术,应用于与服务器进行异步交互功能的实现。
下面来进行传统Web和Ajax进行一个简单的对比,在JavaWeb中你做过这样的jsp页面,在请求的时候使用的是全局的刷新,从一个页面跳到另外一个页面去,虽然可能页面的内容变化不大,但需要从服务器重新加载网页,用图示来看一下:
传统Web模式用户在从网页1切换到网页2或在页面中实现刷新时所触发的HTTP请求则需要服务器饭返回一个新的页面(即存在网页1和网页2);
使用Ajax技术的页面则通过Ajax与服务器之间进行通信,如图示中的客户端发起1.request请求之后随之Web服务器响应2.response请求返回页面1(存在网页1文件),此时要切换到网页2(不存在网页2文件)则通过Ajax对象与服务器进行通信,然后通过DOM操作返回的结果更新到页面中,整个过程都在网页1中进行(不存在网页2文件,网页2的效果是从1更新得到的),听到这会应该知道了Ajax技术了吧,下面来小结一下Ajax技术的优势有啥:
Ajax技术优势
(1)减轻服务器的负担;
Ajax 是按需加载的,可以在很大程度地减少冗余请求和响应服务器造成的负担。
(2)节省宽带;
Ajax 将原来需要服务器做的工作转移到客户端,从而减轻服务器和宽度负担。
(3)用户体验好
Ajax 是按需加载,不刷新更新网页,在不需要重新载入整个页面的情况可以通过DOM操作
及时更新页面内容,不像传统Web应用模式,需要等待白屏和进度条更新页面内容。
Ajax如何发送请求
创建 Ajax 对象
Ajax如何发送请求?首先需要有Ajax对象,然后才可以发起请求。那么如何来创建Ajax对象呢?通过XMLHTTPRequest构造函数创建 Ajax 对象,当然了Ajax早在IE5的时候就出现了,所以有不同的创建对象方式解决IE5和IE6一些不兼容的浏览器,一般都会使用被W3C组织标准化的XMLHTTPRequest,如下:
var xhr = new XMLHTTPRequest()
IE5和IE6浏览器执行代码 :
var xhr = ActiveXObject("Microsoft.XMLHTTP")
Ajax 向服务器发起请求
Ajax向服务器发起请求,首先需要准备一下服务器以及对应的接口,那么就来用经常提到的Node.js 来搭载一个简单的服务器,可以参考一下这篇文章:搭载Node.js服务器 ,搭载完成之后启动服务器:
使用 Postman 来测试一下接口:
可以看到有响应结果,下面来对该接口进行一个描述待用:
API接口 | http://127.0.0.1:3000/ajax/getInfo |
Method | GET请求 |
是否参数 | 无 |
在编写Ajax发起请求代码之前先来了解一下常用的三个方法 open() ,send() 和 setRequestHeader() 方法;
open()
open() 用于创建一个新的HTTP请求,可以指定请求方式、请求URL等如下格式:
open('method', 'URL', [,asyncFlag ,[ 'username'[ ,'password']]])
method 不区分大小写 ps: POST/post GET/get
URL 请求参数
asyncFlag [可选参数],指定请求方式,如:同步为false, 异步为true, 默认为false
username和password [可选参数],HTTP认证用户名密码
send()
send() 方法用于发送请求到Web服务器并接收响应,格式如下
send(content)
content为指定要发送的数据,一般与POST结合使用
请求为同步,则send()会等待请求完成或超时返回
请求为异步,则send()会立即返回
setRequstHTTPRequest()
setRequestHTTPRequest() 用于单独指定某个请求头,格式如下:
setRequestHeader('Header', 'Value')
* 此方法必须在open()后调用
在目标目录下创建 index.html 文件,然后来编写请求:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ajax</title>
</head>
<body>
<script>
// 创建ajax对象
var xhr = new XMLHttpRequest();
// GET - /ajax/getInfo - 无参数 - 无请求头 - 同步
xhr.open("GET" ,"http://127.0.0.1:3000/ajax/getInfo")
xhr.send();
</script>
</body>
</html>
在浏览器中查看一下效果:
可以获取到搭载Node.js服务器上的接口数据,那么如何来处理服务器返回来的信息呢?
处理服务器返回的信息
请求已经发出去了,等待服务器响应返回数据信息,当服务器返回信息时Ajax如何来对服务器返回的信息进行处理有这样几个属性:readyState属性、onreadystatechange属性、status属性和获取响应信息的 responseText 和 responseXML 属性。
readyState 属性
该属性可以获取 Ajax的当前状态,5种形式如下:
状态值 | 说明 | 解释 | 属性名 |
---|---|---|---|
0 | 未发送 | 对象已经创建,尚未调用open()方法 | .UNSENT |
1 | 已打开 | open()方法已调用,此时可以调用send()方法发起请求 | .OPENED |
2 | 收到响应头 | send()方法已调用,响应头已经被接收 | .HEADERS_RECEIVED |
3 | 数据接收中 | 响应体正在被接收,responseText将会在载入的过程中拥有部分响应数据 | .LOADING |
4 | 完成 | 数据接收完毕,可通过responseText获取完成的响应 | .DONE |
onreadystatechange 属性
当从这个属性名就可以猜到 onreadystatechange 可以监听 readyState 属性状态的改变,每当 readyState 的值发生改变时,就会调用此事件,调整一下index.html代码:(不再演示自行测试效果即可)
<script>
// 创建ajax对象
var xhr = new XMLHttpRequest();
// GET - /ajax/getInfo - 无参数 - 无请求头 - 同步
xhr.open("GET" ,"http://127.0.0.1:3000/ajax/getInfo")
xhr.onreadystatechange = function(){
console.log(xhr.readyState)
}
xhr.send();
</script>
status 属性
status 属性用于返回当前请求HTTP状态码,请求成功后会返回 200 ,statusText 与 status属性类似,它是一个字符型数据,包含短语 —— OK ,这些可以自行测试效果。
responseText
responseText 将响应的信息作为字符串返回,而responseXML则是将响应信息格式化为 XML Document 对象返回(只读),请求失败或内容无法解析均是null值,服务器在返回XML时需设置响应头: Content-Type: text/xml 或 application/xml
以上时处理返回信息服务器返回信息相关属性的了解认识,下面通过以上这些来使用Ajax请求发起GET和POST请求;需要在Node.js服务器中编写对应的请求接口,这里暂不提供,如有需要可以在评论区留言。
Ajax - GET 请求
Node.js搭载的服务器端接口API已经准备好了,下面来通过ajax发起GET请求:
API接口 | http://127.0.0.1:3000/ajax/getInfo |
Method | GET请求 |
是否参数 | 无 |
创建 getInfo.html文件编写如下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>getInfo</title>
</head>
<body>
<script>
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://127.0.0.1:3000/ajax/getInfo")
xhr.onreadystatechange = function(){
// 请求成功时打印
if(xhr.readyState == 4 && xhr.status == 200){
// xhr.readyState = 4 则请求完成
// xhr.status = 200 则请求成功
console.log(xhr.responseText)
}
};
xhr.send();
</script>
</body>
</html>
可以看到打印出来的时响应信息,好像跟平常的不大一样,JSON.stringfig() 则是转为字符串,而 JSON.parse() 则是解析字符串为json格式,如下:
console.log(JSON.parse(xhr.responseText))
效果如下:
以上这块内容就是使用ajax来发送get请求,下面来看POST请求;
Ajax - POST 请求
在进行Ajax开发时,经常使用GET方式和POST方式发送请求,GET方式适合从服务器获取数据,POST方式适合向服务器发送数据,这两种方式都可以使用URL参数来传递一些数据,在使用POST请求方式发送数据时,需要设置内容的编码格式来告诉服务器用什么格式来解析编码。下面先来看一下Node.js搭载的后台服务器API接口:
API接口 | http://127.0.0.1:3000/ajax/tologin |
Method | POST请求 |
是否参数 | 是 |
参数信息 | username (String),password(String) |
请求成功 | username = syan,password = 123456 { code: 0 ,message:{ status: 200,msg: '登录成功' } } |
请求失败 | username ≠ syan,password ≠ 123456 { code: 1 ,messgae:{ status:200,msg: '登录失败' } } |
Postman测试API接口:
创建 login.html 页面来编写代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login</title>
</head>
<body>
<script>
var xhr = new XMLHttpRequest();
xhr.open("POST","http://127.0.0.1:3000/ajax/tologin")
// 设置请求头,告诉服务器如何解析
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8")
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
console.log(JSON.parse(xhr.responseText))
}
}
xhr.send("&username=syan&password=123456")
</script>
</body>
</html>
测试效果:
POST请求需要设置请求头setRequestHeader来告诉服务器需要使用什么编码来解析,以及POST请求需要发送什么指定数据,如请求参数可以通过send()方法进行发送,以上就是Ajax发送POST请求的内容。
数据交换格式 XML / JSON
前后端确保通信双方能够准确识别对方发送信息则需要约定一种格式来做数据交换,常用的交换格式就有 XML 和 JSON 两种。
XML 数据格式
XML是可拓展标记语言,XML主要用于描述和存储数据,可以自定义标签,与HTML都是标签语言,下面来看一个简单XML文档,在实际开发者,XML通常不是一个静态的资源,基本是通过程序的处理最后得到的:
那么在Node.js后台搭载API接口可以使用通过一个数组,然后使用for循环拼接字符串得到然后进行反馈即可,下面来用postman测试一下接口:
用表格来描述一下 API 接口:(这里要非常注意的是在搭载Node服务器编写API接口时,记得为该接口设置请求头:setHeader("Content-Type","application/xml"),否则请求接口返回时在Ajax中使用responseXML无法解析)
API接口 | http://127.0.0.1:3000/ajax/xml |
Method | POST请求 |
是否参数 | 无 |
编码格式 | XML |
下面来创建 xml.html 文件来编写代码,请求该接口后返回的XML数据通过Ajax对象的responseXML进行数据处理。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>XML</title>
</head>
<body>
<script>
var xhr = new XMLHttpRequest();
xhr.open("POST","http://127.0.0.1:3000/ajax/xml");
xhr.onreadystatechange = function () {
if ( xhr.readyState == 4 && xhr.status == 200 ) {
console.log(xhr.responseText);
console.log(xhr.responseXML);
let result = xhr.responseXML
let user_one = result.getElementsByTagName('user')[0]
let user_two = result.getElementsByTagName('user')[1]
// 节点
console.log(user_one.childNodes)
console.log(user_two.childNodes)
// 打印值
console.log(user_one.textContent)
console.log(user_two.textContent)
}
}
xhr.send()
</script>
</body>
</html>
测试效果:
除了上述的这种XML数据格式还有就是现如今流行的 JSON 数据格式,这个就不再多讲了,在上面 Ajax-GET请求 返回的数据使用 JSON.parse() 方法进行解析字符串为对象,相对于XML数据格式来说JSON对象访问属性的方法获取数据更为方便,同时在Javascript中可以轻松将JSON对象和字符串进行转化,JSON.stringfiy() 转字符串,JSON.parse()解析成对象。
Ajax 跨域
相关跨域的内容篇目其实讲过蛮多的了,我们都知道出于安全,浏览器中禁止跨域请求的,那么为什么我们刚刚在请求的时候好像没有出现跨域请求的问题;
如上图服务器和客户端不同源可访问成功请求结果打印在了控制台,这是在搭Node.js服务器的时候就解决了跨域访问使用的是CORS,跨域的方式有JSONP,反向代理等跨域的方式,感兴趣的可以看一下这篇文章:十二、Express接口编写 —— 跨域问题_express接口跨域
那么下面我们来将搭载的Node服务器关闭掉解决跨域的中间件,然后来看一下跨域请求报错的样子:
这是因为跨域请求会导致网页失去安全性,所以被浏览器所阻止,浏览器遵循同源策略,同源指的是 URL地址中的协议 、域名 和 端口 都要相同。下面来个图示简单了解:
协议不同 | http://127.0.0.1:3000 | https://127.0.0.1:3000 |
域名不同 | http://www.lhxz.com | http://www.baidu.com |
端口不同 | http://127.0.0.1:3000 | http://127.0.0.1:5500 |
通过以上我们也就知道了浏览器阻止Ajax跨域请求,当目标服务器主动允许跨域请求时,即后台解决了跨域访问的问题,Ajax就能实现跨域访问。
封装Ajax请求 —— Promise
Promise 是 ES6的内容,在代码层上 promise 解决了 "回调地狱" 的问题,什么是回调地狱?这里不用文邹邹的描述,就用直白一点的吧,就是一个异步请求执行完成后执行下一个异步操作,以此嵌套下去,嵌套越多,代码可读性差,还有当我下一个请求需要上一个请求返回的内容就需要等,这样一来就会形成 "回调地狱",那么我们避免在Ajax请求中出现 "回调地狱" 的问题就可以利用 Promise 对象提供的语法进行解决,其中有两个参数 resolve 和 reject ,属于高阶函数(函数里包函数)。请求成功调用 resolve ,请求失败调用 reject ,下面来用一个 js 文件编写引入作为模块,当然你要在script标签编写也可以。
// 封装ajax —— Promise
function xhr (options) {
return new Promise(function(resolve,reject){
const xhr = new XMLHttpRequest();
// METHOD: GET/POST
xhr.open(options.type || 'GET', options.url)
// onreadystatechange
xhr.onreadystatechange = function () {
if(xhr.readyState === XMLHttpRequest.DONE){ // XMLHTTPRequest.DONE : 4
if(xhr.status >= 200 && xhr.status <= 300 || xhr.status === 304){
// success
resolve(xhr.responseText)
}else{
// fail
reject('ERROR: SERVER ERROR ...')
}
}
}
// data为请求参数
xhr.send(options.data)
})
}
引入并调用:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ajax</title>
<script src="./public/js/ajax.js"></script>
</head>
<body>
<script>
// var xhr = new XMLHttpRequest();
// xhr.open("GET" ,"http://127.0.0.1:3000/ajax/getInfo")
// xhr.setRequestHeader("Access-Control-Allow-Origin","*")
// xhr.onreadystatechange = function(){
// console.log(xhr.responseText)
// }
// xhr.send();
// 调用封装ajax
// xhr({ type: 请求方式 , url: 请求地址 })
(function(){
xhr({ type: 'GET', url: 'http://127.0.0.1:3000/ajax/getInfo' })
.then(function(data){ console.log(data) }) // success
.catch(function(err){ console.log(err) }) // fail
})()
</script>
</body>
</html>
如果是POST请求,那么刚刚的封装显然是欠佳的,因为Post 请求头是需要设置的,所以对原来的封装进行调整然后测试一下Post请求:
// 封装ajax —— Promise
function xhr (options) {
return new Promise(function(resolve,reject){
const xhr = new XMLHttpRequest();
// METHOD: GET/POST
xhr.open(options.type || 'GET', options.url)
// setHeader
xhr.setRequestHeader("Content-Type", options.setHeader || 'application/x-www-form-urlencoded')
console.log(options)
// onreadystatechange
xhr.onreadystatechange = function () {
if(xhr.readyState === XMLHttpRequest.DONE){ // XMLHTTPRequest.DONE : 4
if(xhr.status >= 200 && xhr.status <= 300 || xhr.status === 304){
// success
resolve(xhr.responseText)
}else{
// fail
reject('ERROR: SERVER ERROR ...')
}
}
}
xhr.send(options.data)
})
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login</title>
<script src="./public/js/ajax.js"></script>
</head>
<body>
<script>
// var xhr = new XMLHttpRequest();
// xhr.open("POST","http://127.0.0.1:3000/ajax/tologin")
// // 设置请求头,告诉服务器如何解析
// xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8")
// xhr.onreadystatechange = function(){
// if(xhr.readyState == 4 && xhr.status == 200){
// console.log(JSON.parse(xhr.responseText))
// }
// }
// xhr.send("&username=syan&password=123456")
xhr({ type: 'POST', url: 'http://127.0.0.1:3000/ajax/tologin',
data: "&username=syan&password=123456", setHeader: "application/x-www-form-urlencoded; charset=UTF-8"})
.then(function(data){ console.log(data) }) // success
.catch(function(err){ console.log(err) }) // fail
</script>
</body>
</html>
测试一下效果:
ajax封装的内容就到此结束了,我们的篇目也随之来到尾声,本篇讲到了什么是Ajax?Ajax的优势有哪些,如何来发起Ajax?以及使用Ajax来发起GET和POST请求,Ajax跨域的问题 以及 使用 Ajax处理数据 XML 和 JSON 格式转化的问题,让大家更好的了解到什么是Ajax,那么本篇内容就到此结束啦,感谢大家的支持,创作不易,点赞关注一下吧!