Ajax学习笔记——Ajax基础总结
1. AJAX 简介
AJAX 全称为 Asynchronous JavaScript And XML,就是异步的 JS 和 XML。通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:==无刷新获取数据==。AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。
2. AJAX特点
2.1AJAX 的优点
可以无需刷新页面而与服务器端进行通信。
允许你根据用户事件来更新部分页面内容。
2.2 AJAX 的缺点
没有浏览历史,不能回退
存在跨域问题(同源)
SEO 不友
3.使用
3.1 XMLHttpRequest
有关Ajax的所有操作都是通过XMLHttpRequest
来操作的。
3.2 服务端的准备
在使用Ajax之前,因为需要对服务端发送请求,因此这里使用express
框架,创建server.js
文件搭建一个服务器。由于Ajax默认是服从同源策略,因此在服务器中设置Access-Control-Allow-Origin
响应头在解决跨域问题(CORS跨域)。
// server.js const express = require('express') // 创建应用对象 const app = express() // 创建路由规则 app.get('/index', (request, response) => { // 设置允许跨域的响应头 response.setHeader('Access-Control-Allow-Origin', '*') // 设置响应体 response.send('hello ajax') }) app.post('/index', (request, response) => { response.setHeader('Access-Control-Allow-Origin', '*') response.send('post ajax') }) // 监听端口,启动服务 app.listen(8282, () => { console.log('服务器启动,8000端口监听中...'); }) 复制代码
在测试过程中,要保证服务端处于开启状态,开启命令:node server.js
3.3 ajax发送get请求
准备一个html
文档,点击按钮向接口http://127.0.0.1:8282/index
发送请求,请求的数据显示在div
中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ajax get请求</title> <style> .result{ border: 1px solid black; width: 250px; height: 150px; } </style> </head> <body> <button>发送请求</button> <br> <br> <div class="result"></div> <script> let button = document.getElementsByTagName('button')[0] let divObj = document.getElementsByClassName('result')[0] button.addEventListener('click', function(){ // 创建对象 const xhr = new XMLHttpRequest() // 设置请求方法和url xhr.open('GET', 'http://127.0.0.1:8282/index') // 发送请求 xhr.send() // 处理服务端返回的结果 xhr.onreadystatechange = function() { /* readyState属性值: 0 - 对象未初始化 1 - open方法执行 2 - send方法执行 3 - 服务端返回部分结果 4 - 服务端返回全部结果 */ if(xhr.readyState === 4) { // 判断响应状态码 2xx成功 if(xhr.status >= 200 && xhr.status < 300) { // 响应行 // console.log(xhr.status) // console.log(xhr.statusText) // 状态描述 // // 响应头 // console.log(xhr.getAllResponseHeaders()) // // 响应体 // console.log(xhr.response) divObj.innerHTML = xhr.response } } } }) </script> </body> </html> 复制代码
结果: 若需要在发送get请求时携带参数,则url应写为:
xhr.open('GET', 'http://127.0.0.1:8282/index?a=100&b=200&c=300') 复制代码
3.4 发送post请求
将原来代码中xhr.open()
第一个参数右GET
改为POST
:
xhr.open('POST','http://127.0.0.1:8282/index') 复制代码
使用post方法发送请求体时,要将请求体内容放在send
方法中,格式不固定,只要服务端能够处理即可:
// 形式一 xhr.send('a=100&b=200&c=300') // 形式二 xhr.send('a:100&b:200&c:300') // ... 复制代码
3.5 设置请求头信息
// Content-Type 请求体类型 // application/x-www-form-urlencoded 查询字符串类型 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') 复制代码
自定义请求头
xhr.setRequestHeader('Name', 'Alice') 复制代码
此时服务端需要设置Access-Control-Allow-Headers
字段,表示可以接收处理的请求头,否则会报错:
app.post('/index', (request, response) => { response.setHeader('Access-Control-Allow-Origin', '*') response.setHeader('Access-Control-Allow-Headers', '*') response.send('post ajax') }) 复制代码
一般可以在请求头中存放服务端要校验的信息。
3.6 服务端响应 json数据时
服务端若需要将json对象的数据返回给客户端,需要将其转为JSON字符串再发送,server.js
添加代码如下:
// all()表示可以匹配所有请求的方法 app.all('/json-data', (request, response) => { response.setHeader('Access-Control-Allow-Origin', '*') response.setHeader('Access-Control-Allow-Headers', '*') // 响应json数据,需要将json对象转为字符串格式 const data = { 'name': 'Alice', 'age': 34 } response.send(JSON.stringify(data)) }) 复制代码
客户端处理结果时,需要将json字符串转为json对象:
button.addEventListener('click',function() { let xhr = new XMLHttpRequest() xhr.open('GET', 'http://127.0.0.1:8282/json-data') xhr.send() xhr.onreadystatechange = function() { if(xhr.readyState === 4) { if(xhr.status >= 200 && xhr.status < 300) { // 将服务端返回的json数据转为json对象 let data = JSON.parse(xhr.response) console.log(data) } } } }) 复制代码
控制台: 或者可以直接在xhr
对象上设置响应体类型为json
,就不用执行转换步骤:
button.addEventListener('click',function() { let xhr = new XMLHttpRequest() xhr.responseType = 'json' xhr.open('GET', 'http://127.0.0.1:8282/json-data') xhr.send() xhr.onreadystatechange = function() { if(xhr.readyState === 4) { if(xhr.status >= 200 && xhr.status < 300) { let data = xhr.response console.log(data) } } } }) 复制代码
控制台:
3.7 解决IE缓存问题
在IE浏览器中,发送Ajax请求回来的数据会被缓存,导致在某些时效性比较强的场景下会得到错误的数据。因此需要在url
中携带一个表示时间戳的参数,使得IE浏览器认为每次都在发送不同的请求:
xhr.open('get', 'http://127.0.0.1:8282/json-data?t='+Date.now()) 复制代码
3.8 请求超时和网络异常处理
可以在xhr
对象上设置超时时间,若在这个时间之内没有获取到响应结果,则会自动取消。例如,在服务端设置3秒后返回结果:
// 延迟响应 app.get('/delay', (request, response) => { response.setHeader('Access-Control-Allow-Origin', '*') setTimeout(() => { response.send('延迟响应') }, 3000) }) 复制代码
客户端设置超时时间为2s
<script> let button = document.getElementsByTagName('button')[0] let divObj = document.getElementsByTagName('div')[0] button.addEventListener('click', function() { let xhr = new XMLHttpRequest() // 设置超时2s取消请求 xhr.timeout = 2000 // 超时回调 xhr.ontimeout = function() { alert('网络较慢,请稍后重试!') } xhr.open('GET', 'http://127.0.0.1:8282/delay') xhr.send() xhr.onreadystatechange = function() { if(xhr.readyState === 4) { if(xhr.status >= 200 && xhr.status < 300) { divObj.innerHTML = xhr.response } } } }) </script> 复制代码
控制台: 也可以设置网络异常时的回调:
xhr.onerror = function() { alert('网络异常!') } 复制代码
在浏览器中,将网络状态设为offline
,模拟没有网络的情况
3.9 取消请求
xhr
对象上的abort()
可以用于取消请求:
xhr.abort() 复制代码
3.10 重复发送请求问题
当我们多次点击按钮发送请求时,会对服务器造成一定压力,且多次请求的操作并不是必要的,解决这个重复请求问题,需要当再次发送请求时,把上一次没完成的请求取消掉。
<body> <button>发送请求</button> <script> let button = document.getElementsByTagName('button')[0] // 是否正在处理ajax请求的标识 let isSending = false let xhr button.addEventListener('click', function() { // 如果上一次请求还在,取消,重新发起请求 if(isSending) { xhr.abort() } xhr = new XMLHttpRequest() isSending = true xhr.open('GET', 'http://127.0.0.1:8282/delay') xhr.send() xhr.onreadystatechange = function() { if(xhr.readyState === 4) { // 请求处理完,无论状态码是什么,都是为false isSending = false } } }) </script> </body>
作者:前端小木屋
链接:https://juejin.cn/post/6997333407583862814