目录
1,什么是 AJAX
2,AJAX优缺点
2.1,AJAX 的优点
2.2, AJAX 的缺点
3,AJAX如何工作
4,原生AJAX
4.1,XMLHttpRequest
4.2,服务端准备
4.3,发送AJAX请求
4.3.1,发送get请求
4.3.2,发送post请求
4.4.3,设置请求头信息
5,AJAX响应时问题
5.1,服务端响应 json数据时
5.2,请求超时和网络异常处理
5.3,取消发送
5.4,重复发送请求
6,用不同方法发送AJAX请求(非原生)
6.1,jQuery发送AJAX请求
6.1.1,准备
6.1.2, $.ajax()
6.1.3, $.post()
6.1.4, $.get()
6.2,axios发送请求
6.2.1,准备
6.2.2,方式 (最为简单,简洁)
6.3,fetch发送请求
7,同源策略和解决跨域问题
7.1,同源策略
7.1.1,什么是同源策略
7.1.2,同源策略的限制内容
7.2,跨域
7.2.1,跨域的原理
7.2.2, JSONP跨域
7.2.3,CORS跨域
AJAX = Asynchronous JavaScript And XML。AJAX 并非编程语言!
AJAX 仅仅组合了:
Ajax 是一个令人误导的名称。Ajax 应用程序可能使用 XML 来传输数据,但将数据作为纯文本或 JSON 文本传输也同样常见。
通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:==无刷新获取数据==。AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。
有关Ajax的所有操作都是通过XMLHttpRequest
来操作的。
在使用Ajax之前,因为需要对服务端发送请求,因此这里使用express
框架,创建server.js
文件搭建一个服务器。由于Ajax默认是服从同源策略,因此在服务器中设置Access-Control-Allow-Origin
响应头在解决跨域问题(CORS跨域)。(详见代码解析)
//1.引入express
const { request, response } = require('express');
const express = require('express');
//2.创建应用对象
const app = express();
//3.创建路由规则(GET和POST分别创建)
//request是对请求报文的封装
//response是对相应报文的封装
//GET请求
app.get('/server',(request,response)=>{
//设置相应头
response.setHeader("Access-Control-Allow-Origin", "*");
//设置相应体
response.send('HELLO AJAX agaion');
});
//POST请求
app.post('/server',(request,response)=>{
//设置相应头
response.setHeader("Access-Control-Allow-Origin", "*");
//设置相应体
response.send('HELLO AJAX POST')
});
//4.监听端口启动服务端
app.listen(8000,()=>{
console.log("服务已经启动,8000 端口监听中......");
});
在测试过程中,要保证服务端处于开启状态,开启命令:node server.js
准备一个html
文档,点击按钮向接口http://127.0.0.1:8000
发送请求,请求的数据显示在console(控制台)中。
将原来代码中xhr.open()
第一个参数右GET
改为POST
XMLHttpRequest 对象方法
方法 | 描述 |
---|---|
new XMLHttpRequest() | 创建新的 XMLHttpRequest 对象 |
abort() | 取消当前请求 |
getAllResponseHeaders() | 返回头部信息 |
getResponseHeader() | 返回特定的头部信息 |
open(method, url, async, user, psw) | 规定请求
|
send() | 将请求发送到服务器,用于 GET 请求 |
send(string) | 将请求发送到服务器,用于 POST 请求 |
setRequestHeader() | 向要发送的报头添加标签/值对 |
XMLHttpRequest 对象属性
属性 | 描述 |
---|---|
onreadystatechange | 定义当 readyState 属性发生变化时被调用的函数 |
readyState | 保存 XMLHttpRequest 的状态。
|
responseText | 以字符串返回响应数据 |
responseXML | 以 XML 数据返回响应数据 |
status | 返回请求的状态号
如需完整列表请访问 Http 消息参考手册 |
statusText | 返回状态文本(比如 "OK" 或 "Not Found") |
// 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')
})
复制代码
一般可以在请求头中存放服务端要校验的信息。
服务端若需要将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: '洋芋炒土豆',
age: 20
}
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)
}
}
}
})
可以在xhr
对象上设置超时时间,若在这个时间之内没有获取到响应结果,则会自动取消。例如,在服务端设置3秒后返回结果:
// 延迟响应
app.get('/delay', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*')
setTimeout(() => {
response.send('延迟响应')
}, 3000)
})
客户端设置超时时间为2s:
xhr
对象上的abort()
可以用于取消请求:
当我们多次点击按钮发送请求时,会对服务器造成一定压力,且多次请求的操作并不是必要的,解决这个重复请求问题,需要当再次发送请求时,把上一次没完成的请求取消掉。
代码:
我们可以使用JavaScript的对象XMLHttpRequest来实现原生Ajax,但这种方法比较复杂,不易编写。jQuery已经封装了Ajax,使得发起Ajax请求比较容易,这里我们首先需要在
标记中引入jQuery.js文件。例如:
形式:$.ajax({name:val, name:val,...});
可选字段:
形式:$.post(url, data, func, dataType);
可选参数:
形式:$.get(url, data, func, dataType);
其各个参数所示意义与$.post()一致,在此不再列出,区别是请求类型是GET。
fetch号称是ajax的替代品,fetch是一种HTTP数据请求的方式,是XMLHttpRequest的一种替代方案。fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象。
Fetch API 主要有两个特点:一是接口合理化,AJAX 是将所有不同性质的接口都放在 XHR 对象上,而Fetch是将它们分散在几个不同的对象上,设计更合理;二是Fetch操作返回 Promise 对象,避免了嵌套的回调函数。
由于fetch本身就是js的自带属性,所以不需要引入其他封装包。
协议://域名:(端口号)
同源策略限制以下几种行为:
同源策略
造成的。避开浏览器的安全限制
。(1)原理:
JSONP
通过同源策略涉及不到的"漏洞",也就是像img
中的src
,link
标签的href
,script
的src
都不受同源策略的限制。(2)步骤:
// 动态创建 script
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript')
// 设置回调函数,用于后端返回的js代码中进行调用
function getData(data) {
console.log(data);
}
//设置 script 的 src 属性,并设置请求地址
script.src = 'http://localhost:3000/?callback=getData';
// 让 script 生效
document.body.appendChild(script); //将返回的文本插入页面执行,让script调用回调函数
(3)JSONP 的缺点:
JSON 只支持 get,因为 script 标签只能使用 get 请求; JSONP 需要后端配合返回指定格式的数据。
添加请求头实现跨域。
response.setHeader("Access-Control-Allow-Headers", "*");