AJAX简介
AJAX全称Asynchronous javascript And XML,就是异步的JS和XML
通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。
AJAX不是新的编程语言,不是新的一门独立的技术,而是一种使用现有标准的新方法。
XML简介
XML可扩展标记语言
XML被设计用来传输和存储数据
XML和HTML类型,不同的是HTML中都是预定义标签,而XML中没有预定义标签,全都是自定义标签,用来表示一些数据
比如说我有一个学生数据
name="孙悟空";age=18;gender="男"
用XML表示:
<student>
<name>孙悟空</name>
<age>18</age>
<gender>男</gender>
</student>
现在已经被JSON取代了
用JSON表示:
{"name":"孙悟空","age":18,"gender":"男"}
AJAX的工作原理
Ajax的工作原理相当于在用户和服务器之间加了一个中间层(Ajax引擎),使用户操作与服务器响应异步化。
AJAX的特点
AJAX的优点
1.可以无需刷新页面而与服务器进行通信
2.允许你根据用户事件来更新部分页面内容
AJAX的缺点
1.没有浏览历史,不能回退
2.存在跨域问题
3.SEO不友好
核心对象
XMLHttpRequest,AJAX的所有操作都是通过该对象进行的
原生AJAX
server.js
//1.引入express
let express = require('express')
//2.创建app服务对象
let app = express()
//暴露静态资源
app.use(express.static('public'))
//解析POST请求请求体中以urlencoded形式编码参数
app.use(express.urlencoded({extended:true}))
app.get('/test_get',(request,response)=>{
console.log('一个GET请求来了',request.query)
response.send('我是服务器响应GET请求的信息')
})
app.post('/test_post',(request,response)=>{
console.log(request.body)
console.log('一个POST请求来了')
response.send('我是服务器响应POST请求的信息')
})
//4.绑定端口监听
app.listen(3000,(err)=>{
if (!err) {
console.log('【不要使用webstorm打开html页面,会存在跨域问题!!用以下地址】')
console.log('测试原生js发送Ajax-GET请求的地址是:http://localhost:3000/ajax_get.html')
console.log('测试原生js发送Ajax-POST请求的地址是:http://localhost:3000/ajax_post.html')
console.log('测试自己封装的Ajax请求的地址是:http://localhost:3000/ajax_with_promise.html')
}
else console.log(err)
})
public/ajax_get.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试原生jS发送Ajax-GET请求</title>
</head>
<body>
<h2>该页面是测试使用原生js发送Ajax-GET请求</h2>
<button id="btn">点我使用原生js发送Ajax-GET请求</button>
<div id="demo"></div>
<script type="text/javascript">
/*
* 1.实例化一个XMLHttpRequest对象。
* 2.给该对象绑定一个事件监听,名称为:onreadystatechange。
* 3.指定发请求的:方式、地址、参数。
* 4.发送请求。
* */
let btn = document.getElementById('btn')
btn.onclick = function () {
//1.实例化一个XMLHttpRequest对象。
let xhr = new XMLHttpRequest()
//2.给该对象绑定一个事件监听,名称为:onreadystatechange。
xhr.onreadystatechange = function () {
/*
* 在xhr内部有5种状态:
* -0:当xhr被实例化出来,状态就是0,即:初始化状态。
* -1:请求还没有发出去,即:send方法还没有被调用,依然可以修改请求头。
* -2:请求已经发出去了,即:send方法已经被调用了,不能再修改请求头,响应首行和响应头已经回来了。
* -3:数据回来了(但是数据可能不完整,如果数据小,会在此阶段直接接收完毕,数据大有待于进一步接收)
* -4:数据完全回来了
* */
//备注:一般不会在0、1、2、3这几种状态的回调中,做任何逻辑。
/*if(xhr.readyState === 0){
console.log('我出生了,我是初始化状态')
}*/
/*if(xhr.readyState === 1){
xhr.setRequestHeader('demo',123)
console.log('请求还没有发出去,即:send方法还没有被调用,依然可以修改请求头。')
}*/
/*if(xhr.readyState === 2){
//xhr.setRequestHeader('demo',123)
console.log('请求已经发出去了,即:send方法已经被调用了,不能再修改请求头,响应首行和响应头已经回来了。')
console.log(xhr.getResponseHeader('Date'));
}*/
/*if(xhr.readyState === 3){
console.log('数据回来了(但是数据可能不完整,如果数据小,会在此阶段直接接收完毕,数据大有待于进一步接收)')
console.log(xhr.response);
}*/
if(xhr.readyState === 4 && xhr.status === 200){
console.log(xhr)
let demo = document.getElementById('demo')
demo.innerHTML = xhr.response
}
}
//3.指定发请求的:方式、地址、参数。
xhr.open('GET','http://localhost:3000/test_get?name=kobe&age=18&t='+Date.now())
//4.发送请求。
xhr.send()
/*
* 对于IE来说:
* 只要请求的地址不发生变化,那么直接走强缓存
* 对于chrome和火狐
* 请求地址不发生变化,尝试请求协商缓存。
* */
}
</script>
</body>
</html>
public/ajax_post.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试原生jS发送Ajax-POST请求</title>
</head>
<body>
<h2>该页面是测试使用原生js发送Ajax-POST请求</h2>
<button id="btn">点我使用原生js发送Ajax-POST请求</button>
<div id="demo"></div>
<script type="text/javascript">
/*
* 1.实例化一个XMLHttpRequest对象。
* 2.给该对象绑定一个事件监听,名称为:onreadystatechange。
* 3.指定发请求的:方式、地址、参数。
* 4.发送请求。
* */
let btn = document.getElementById('btn')
btn.onclick = function () {
//1.实例化一个XMLHttpRequest对象。
let xhr = new XMLHttpRequest()
//2.给该对象绑定一个事件监听,名称为:onreadystatechange。
xhr.onreadystatechange = function () {
if(xhr.readyState === 4 && xhr.status === 200){
console.log(xhr.response)
let demo = document.getElementById('demo')
demo.innerHTML = xhr.response
}
}
//3.指定发请求的:方式、地址、参数。
xhr.open('POST','http://localhost:3000/test_post')
//设置POST请求所特有的请求头!!!!!!
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')
//4.发送请求。
xhr.send('name=kobe&age=18')
}
</script>
</body>
</html>
数组的reduce方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数组的reduce方法</title>
</head>
<body>
<script>
/*
* 【数组的reduce方法】:
* 1.reduce方法接收一个函数作为累加器(“连续操作器”)。
* 2.数组中的每个值(从左到右)开始合并(不一定是相加!),最终为一个值。
* 3.reduce为数组中的每一个元素【依次执行】回调函数,但不包括数组中被删除或从未被赋值的元素。
* 4.reduce方法最终返回的是最后一次调用累加器的结果。
* 5.累加器函数接受四个参数:preValue, nowValue, nowIndex, arr
* --preValue:
* --第一次调用时是初始值,如果初始值没有指定,就是数组中第一个元素的值,同时nowValue变为数组中的第二个值。
* --以后调用时是上一次该回调函数的返回值;
* --nowValue:当前元素值;
* --nowIndex:当前索引;
* --arr:调用 reduce 的数组;
*
* 参数说明:
* array.reduce(function(preValue, nowValue, nowIndex, arr){}, initialValue)
*
* 注意:
* 1.如果initialValue在调用时被提供,那么第一次的preValue就等于initialValue,nowValue等于数组中的第一个值;
* 2.如果initialValue未被提供,那么preValue等于数组中的第一个值,nowValue自动等于数组中的第二个值。
*
* */
let arr = [2,4,6,8]
let result = arr.reduce(function (preValue, nowValue, nowIndex, arr) {
return preValue + nowValue
},100)
console.log(result);
</script>
</body>
</html>
public/ajax_with_promise.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用Promise封装原生Ajax</title>
</head>
<body>
<h2>该页面使用Promise封装了原生Ajax</h2>
<button id="btn1">点我是我使用自己封装的方法发送GET请求</button>
<button id="btn2">点我是我使用自己封装的方法发送POST请求</button>
<script type="text/javascript">
let btn1 = document.getElementById('btn1')
let btn2 = document.getElementById('btn2')
btn1.onclick = function () {
sendAjax('http://localhost:3000/test_get','GET',{m:1,n:2}).then((data)=>{
console.log(data)
}).catch((err)=>{
console.log(err)
})
}
btn2.onclick = function () {
sendAjax('http://localhost:3000/test_post','POST',{m:3,n:4}).then((data)=>{
console.log(data)
}).catch((err)=>{
console.log(err)
})
}
/*;(async()=>{
let {data} = await sendAjax('http://localhost:3000/test_get','GET',{m:1,n:2})
let {data2} = await sendAjax('http://localhost:3000/test_get','GET',{data})
let {data3} = await sendAjax('http://localhost:3000/test_get','GET',{data2})
})()*/
function sendAjax(url,method,data) {
return new Promise((resolve,reject)=>{
//1.创建xhr对象
let xhr = new XMLHttpRequest()
//2.绑定监听
xhr.onreadystatechange = function () {
if(xhr.readyState !== 4){
return
}
if(xhr.readyState === 4 && (xhr.status >= 200 && xhr.status<= 299)){
const responseObj = {
data:xhr.response,
status:xhr.status,
statusText:xhr.statusText
}
resolve(responseObj)
}else{
reject(new Error('请求出错了'))
}
}
//3.设置请求的方式,地址,携带的参数
let dataKeys = Object.keys(data)
//4.将传递过来的数据对象加工成urlencoded形式的编码
let str = dataKeys.reduce(function (pre,now) {
return pre+=`${now}=${data[now]}&`
},'')
//5.发送请求
if(method.toLowerCase() === 'get'){
url += `?${str}`
xhr.open(method,url)
xhr.send()
}else if (method.toLowerCase() === 'post'){
xhr.open(method,url)
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')
xhr.send(str)
}
})
}
</script>
</body>
</html>
取消上一次请求
server.js
//1.引入express
let express = require('express')
//2.创建app服务对象
let app = express()
app.use(express.static('public'))
//根路由
app.get('/get_code',(request,response)=>{
/*
* 返回一个1000 - 9999
* */
console.log('客户端发来了获取验证码的请求')
setTimeout(function () {
let code = Math.floor(Math.random()*8999 + 1000)
response.send(code.toString())
},2000)
})
//4.绑定端口监听
app.listen(3000,(err)=>{
if (!err) console.log('http://localhost:3000/')
else console.log(err)
})
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>取消上一次请求</title>
</head>
<body>
<button id="btn">点我获取验证码</button>
<script type="text/javascript">
let btn = document.getElementById('btn')
let lastXhr
btn.onclick = function () {
if(lastXhr){
lastXhr.abort()
}
lastXhr = getCode()
}
function getCode() {
let xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
if(xhr.readyState === 4 && xhr.status === 200){
console.log(xhr.response)
}
}
xhr.open('GET','http://localhost:3000/get_code')
xhr.send()
return xhr
//xhr.abort()
/*
* abort()取消本次请求(拦截回来的响应)。
* */
}
</script>
</body>
</html>
jQuery封装的Ajax
server.js
//引入express框架
let express = require('express')
//创建app应用对象
let app = express()
//暴露静态资源
app.use(express.static('public'))
//引入服务器内部具体实现
app.disable('x-powered-by')
//用于解析post请求的请求体参数
app.use(express.urlencoded({extended:true}))
app.get('/test_get',(request,response)=>{
console.log(request.query);
console.log('test_get路由被调用了')
response.send('我是服务器返回的GET请求的信息')
})
app.post('/test_post',(request,response)=>{
console.log(request.body);
console.log('test_post路由被调用了')
response.send('我是服务器返回的POST请求的信息')
})
app.listen(3000,(err)=>{
if(!err) console.log('测试jQuery封装的Ajax请求的地址是:http://localhost:3000/jquery_ajax.html')
else console.log(err)
})
public/jquery_ajax.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用jQuery发送Ajax请求</title>
</head>
<body>
<h2>该页面是测试:jQuery发送Ajax请求</h2>
<button id="btn1">点我使用jQuery发送Ajax-GET请求</button>
<button id="btn2">点我使用jQuery发送Ajax-POST请求</button>
<script type="text/javascript" src="./js/jquery-1.12.4.js"></script>
<script type="text/javascript">
let btn1 = $('#btn1')
let btn2 = $('#btn2')
btn1.click(function () {
/*
* 使用jQuery发送Ajax-GET请求几个常用的参数
* -method:发送请求的方式
* -data:要传递的数据
* -success:成功的回调
* -error:失败的回调
* */
//使用jQuery发送Ajax-GET请求(标准写法)
$.ajax('http://localhost:3000/test_get',{
method:'GET',
data:{name:'kobe',age:18},
success:function (result) {
console.log(result)
},
error:function (err) {
console.log(err)
}
})
//使用jQuery发送Ajax-GET请求(简写)
$.get('http://localhost:3000/test_get',{name:'kobe',age:18},(data)=>{
console.log(data)
})
})
btn2.click(function () {
/*
* 使用jQuery发送Ajax-GET请求几个常用的参数
* -method:发送请求的方式
* -data:要传递的数据
* -success:成功的回调
* -error:失败的回调
* */
//使用jQuery发送Ajax-POST请求(标准写法)
/*$.ajax('http://localhost:3000/test_post',{
method:'POST',
data:{name:'kobe',age:18},
success:function (result) {
console.log(result)
},
error:function (err) {
console.log(err)
}
})*/
//使用jQuery发送Ajax-POST请求(简写)
$.post('http://localhost:3000/test_post',{name:'kobe',age:18},(data)=>{
console.log(data)
})
})
</script>
</body>
</html>