1. 什么是ajax?
- `async javascript and xml`
+ async 异步
+ javascript
+ and 和
+ xml 是一种严格是html格式数据
- ajax 就是 前后端交互的一种方式(异步交互)
2. 前后端交互
- 前端 和 后端 之间的通讯沟通
- 目的: 通过 ajax 向后端(服务端)送一个请求, 得到服务端返回的结果
+ 比如: 登录, 发送用户名 和 密码,接受返回 登录成功 或 登录失败
1)同步和异步的定义
- js 是单线程的,单线程就是指在同一个时间不能执行多个任务
- 同步: 同步执行那个就是按照顺序执行
- 异步: 不按照顺序执行(跳过执行),异步代码会等所有的同步代码执行结束后,才执行异步代码
3. http传输协议(了解)
根据传输协议规定, 必须是由前端向后端发送请求, 发送请求的时候如果要携带一些参数, 必须是字符串格式。
三次握手的步骤
1. 建立连接通道
浏览器和服务端 建立一个连接
2. 前端(客户端)发送请求
要求前端必须以 '请求报文' 的形式发送;
请求报文 由 浏览器进行组装, 我们只需要提供对应的信息即可;
比如说: 请求的方式, 请求的地址, 请求需要的参数
3. 服务器返回响应
要求后端必须以 '响应报文' 的形式返回;
响应报文内有一个东西叫做响应状态码;
响应状态码
100~199 表明连接还在继续
200~299 表明连接各种成功 但现在只会返回一个 200
300~399 表明请求重定向
400~499 表明请求失败 但现在只会看到一些 403 404 401 400 一般4开头是前端的问题
500~599 表明服务端出错 跟前端无关, 是后端的问题
4. 断开连接
浏览器和服务端的连接断开
4.标准格式
写法1:(推荐)
+ onload事件 只能在标准浏览器中使用 在低版本IE中不能使用
<script>
// 1. 创建一个 ajax 对象
const xhr = new XMLHttpRequest()
// 2. 配置 ajax 配置请求信息 (请求方式,请求地址,是否异步):默认值为true 表示ajax异步,false,表示ajax同步
xhr.open('GET', 'http://localhost:8888/test/first', true)
//3. 接收响应
xhr.onload = function () {//给xhr绑定函数
// console.log('现在后端已经给我们返回了 我们想要的数据了')
console.log(xhr.responseText) //ajax对象的属性responseText存储了响应的数据
// 已经成功使用 ajax 发送给我了一个请求, 这是我给你的回应
}
// 4. 发送请求
xhr.send()
</script>
写法2:(比较少用)
ajax对象的 readystatechange 事件 可以兼容低版本IE
- 触发时机: 当ajax状态码发生变化的时候触发
<script>
// 1. 创建一个 ajax 对象
const xhr = new XMLHttpRequest()
// 2. 配置 ajax对象 (请求方式,请求地址,是否异步):默认值为true 表示ajax异步,false,表示ajax同步
xhr.open('GET', 'http://localhost:8888/test/first')
// 4. 配置接收响应的函数
xhr.onreadystatechange = function () {//给xhr绑定函数
if (xhr.readyState === 4) {
console.log('当前浏览器已经完全解析完毕 返回的数据', xhr.responseText)
//ajax对象的属性responseText存储了响
}
}
// 3. 发送请求
xhr.send()
</script>
1)为什么用上述格式
一下是错误写法,xhr.onload应该放在xhr.send前
<script>
const xhr = new XMLHttpRequest()
xhr.open('GET', 'http://localhost:8888/test/first', false) //false,表示ajax同步
xhr.send()//发送请求,等待返回值并赋给xhr。xhr.send()需要几秒完成,它包括组装报文等操作
//open里如果是true,xhr.send就是异步代码,程序会继续向下运行xhr.onload将方法绑定给xhr。然后等待返回值会赋给xhr,send结束后再触发onload函数
//open里如果是false就是同步步代码,xhr.send()发送一个请求, 等待请求完成后, 开始执行后边的xhr.onload代码,但是xhr.send()已经把这个请求完全的运行结束了, 所以此时不可能再触发这个函数了)
xhr.onload = function () {//相当于给xhr绑定方法
console.log(xhr.responseText)
}
</script>
5. ajax 的状态码
通过一个数字, 表明 ajax 当前运行到那一步了
0 表示ajax对象创建完成 //例如:const xhr = new XMLHttpRequest()后 xhr.readyState=0
1 表示配置本次请求信息完成 //例如:xhr.open('GET', 'http://localhost:8888/test/first')后,xhr.readyState=1
//因为 xhr.send()整个过程中做了以下3个动作:所以状态码从1变为2,从2变为3,从3变为4
2 表示发送请求,并且响应已经回到浏览器的瞬间(响应报文来到浏览器,但是浏览器还没有开始解析响应报文),//xhr.readyState=2
3 表示浏览器正在解析响应报文,并且逐条把响应报文的内容填充到 `xhr.responseText`中,//xhr.readyState=3
4 表示浏览器解析响应结束,并且已经把响应报文全部填充到 `xhr.responseText`中,本次请求结束。//xhr.readyState=4
6. 不同的请求方式
1) get请求方式:
参数的位置:发送请求时,所需要携带的参数(key1=value1&key2=value2)通过?,&拼接(and符号),放在请求地址后
参数的形式:字符串形式
格式:xhr.open('GET', 'http://localhost:8888/test/third?name=zhangsan&age=18')
书写格式:
// 1. 创建一个 ajax 对象
const xhr = new XMLHttpRequest()
// 2. 配置 ajax 对象 xhr.open('请求方式', '请求地址')
xhr.open('GET', 'http://localhost:8888/test/third?name=zhangsan&age=18')//字符串的形式发送请求
// 3. 配置接收响应的函数
xhr.onload = function () {
const res = JSON.parse(xhr.responseText)//将json字符串转化为对象形式
console.log(res)
}
// 4. 发送请求
xhr.send()
2) post请求方式:
参数的位置: 不能拼接在请求地址后,而是放在请求方式 send()的()里
参数的形式: 字符串的形式
格式:xhr.send('name=张三&age=18')
在传参的时候还需要配置一个请求头中的属性 content-type
content-type 赋值的时候, 还要区分我们传递要的参数是普通字符串, 还是 json 格式的字符串。
1) 普通字符串: xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
2) json字符串: xhr.setRequestHeader('content-type', 'application/json')
书写格式:
// 1. 创建一个 ajax 对象
const xhr = new XMLHttpRequest()
// 2. 配置 ajax 对象 xhr.open('请求方式', '请求地址')
xhr.open('POST', 'http://localhost:8888/test/fourth')
// 4. 配置接收响应的函数
xhr.onload = function () {
const res = JSON.parse(xhr.responseText)//将json字符串转化为对象形式
console.log(res)
}
// 3.1 post 请求传参时需要配置 content-type(请求头内的属性)
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
// 3.2 发送请求
xhr.send('name=张三&age=18')//字符串的形式发送请求
7.封装异步(ajax请求)代码
为什么用promise去封装ajax:发送请求包含异步代码,我们不知道onload什么时候触发。ajax是异步代码,封装异步代码的方法
有两个:一个是回调函数,一个是promise. 但是回调函数会遇到回调地狱问题。所以用promise去封装ajax的异步代码
* 需求:
* 1. 请求的方式: 选填, 默认值为 GET; 形参名: type
* 2. 请求的地址: 必填; 形参名: url
* 3. 请求为同步还是异步: 选填, 默认值为 true; 形参名: async
* 4. 请求需要携带参数: 选填, 默认为 ''; 形参名: data
*
* 返回值:
* 需要返回一个 promise 对象, 后续可以通过 .then 或者 async/await 去使用
<script>
function myAjax(options) {//把promise封装到myAjax函数里
// 1. 验证 参数中的 url 必传
if (options.url === undefined) throw new Error('参数中缺少必传项 url') // 返回一个错误
// 1.1 参数格式验证, 拿请求方式举例: type 只接受 undefined 或者 string 两种类型
if (!(options.type === undefined || typeof (options.type) === 'string')) throw new Error('参数中 type 的类型必须为 string')
// 2. 封装默认值
const _options = {
url: options.url, //必填; 形参名: url
type: options.type || 'GET', //选填, 默认值为 GET; 形参名: type
data: options.data || '', //选填, 默认为 ''; 形参名: data
async: options.async ?? true //选填, 默认值为 true; 形参名: async
//空值检测符, 该符号的特点 只会在 左侧的值为空值的时候返回右侧, 比如左侧为: null, undefined。
}
// 3. 如果当前 _options.data 有值, 并且 _options.type 是 GET 方式, 我们直接将 data 拼接到 url 后边
if (_options.data && /^(GET)$/i.test(_options.type)) {
_options.url += '?' + _options.data
//例如:_options.url=http://localhost:8888/test/third?name=zhangsan&age=18
}
// 用promise去封装异步(ajax请求)代码
const p = new Promise((res, rej) => { //直接运行箭头函数里的代码,p用来存储promise对象
const xhr = new XMLHttpRequest() // 创建一个 ajax 对象 xhr
xhr.open(_options.type, _options.url, _options.async) //配置 ajax对象
xhr.onload = function () { //ajax 对象 xhr绑定方法
res(xhr.responseText)//将promise对象p 的状态改为成功,触发then函数并运行里面的代码
}
if (/^(POST)$/i.test(_options.type)) { //如果请求方式是POST
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
xhr.send(_options.data)//发送请求后,如果成功收到后端返回值就会触发onload事件
} else {//如果请求方式不是POST
xhr.send() //发送请求后,如果成功收到后端返回值就会触发onload事件
}
})
return p //返回一个Promise对象 p
}
</script>
使用上述的封装函数
//1. 'POST'方式 使用.then
myAjax({
url: 'http://localhost:8888/test/fourth',
data: 'name=zhangsan&age=18',
type: 'POST'
}).then((res) => {
console.log('我是 .then 内输出的 参数: ', JSON.parse(res))
})
//2. 不传请求方式type 使用.then方法
myAjax({
url: 'http://localhost:8888/test/third',
data: 'name=zhangsan&age=18',
}).then((res) => {
console.log('我是 .then 内输出的 参数: ', JSON.parse(res))
})
//3. 不传请求方式type 使用async-await方法
async function mfAjaxReturn() {
const res = await myAjax({
url: 'http://localhost:8888/test/third',
data: 'name=zhangsan&age=18',
})
console.log(res)
}
mfAjaxReturn()