JavaScript全解析——Ajax(下)
Ajax(下)
●http 传输协议
○http(s) 协议规定了, 只能由前端主动发起
○并且在传输的过程中, 只能传递 字符串
●http 协议过程
1.建立连接
浏览器和服务器进行连接建立
基于 TCP/IP 协议的三次握手
2.发送请求
要求前端必须以 请求报文 的形式发送
报文由浏览器组装, 我们只需要提供对应的信息即可
报文包含的内容
3.接收响应
要求后端必须以响应报文的形式返回
报文由服务器组装
响应报文包含的内容
响应报文行
响应状态码, 简单信息描述响应状态码, 传输协议
响应报文头(对本次响应的一些说明信息)
server: 哪一个服务器给你返回的信息
date: 时间, 服务器时间
content-length: 响应体长度
content-type: 响应数据类型
响应报文体(后端返回给前端的一些信息)
4.断开连接
浏览器和服务器断开连接
基于 TCP/IP 协议的四次挥手
●响应状态码
○100199 表示连接继续299 表示各种成功
○200
○300399 表示重定向499 表示各种客户端错误
○400
○500~599 表示各种服务端错误
●回调函数
○把函数 A 以实参的形式传递到 函数 B 内
○在函数 B 内以形参的方式调用到 函数 A
○此时我们可以把函数 A 叫做函数 B 的 回调函数
○我们在封装异步代码的时候会用到回调函数
●使用回调函数封装一个异步代码
●上述代码已经完成了一个异步的封装
●不过在工作中我们更多的是封装网络请求这种异步代码
●但是我们这里通过一个 '买水耗时' 来模拟一个网络请求的延迟, 我们约定如果时间超过 3500 毫秒, 那么就算是失败, 否则就是成功
●此时我们已经封装完毕了, 只不过这种封装方式会带来另一个问题, 就是回调地狱
●回调地狱: 当你使用回调函数过多的时候, 会出现的一种代码书写结构
●需求:
○再买水成功后, 让班长帮忙退掉
○在推掉以后, 再次让班长帮忙买水 (此时必须要在前一瓶水购买完成之后再去购买)
○在第二次买水成功以后, 再次让班长去买水
●这段代码运行没有任何问题, 但是阅读起来极其不利于理解
○原因:
■按照回调函数的语法进行封装, 只能通过传递一个函数作为参数来调用
■当你使用回调函数过多的时候, 会出现回调地狱的代码结构
○解决:
■不按照回调函数的语法封装
■ES6 推出了一种新的封装异步代码的方式, 叫做 Promise (承诺, 期约)
Promise
是一种异步代码的封装方案
因为换了一种封装方案, 不需要安装回调函数的方式去调用, 需要按照 promise 的形式去调用
注意 promise 不是解决 异步问题的, 而是解决回调地狱问题的
●认识 Promise
○promise 的三种状态
■持续: pending
■成功: fulfilled
■失败: rejected
○promise 的两种转换
■从持续转为成功
■从持续转为失败
○promise 的基础语法
■ES6 内置构造函数
○promise 的语法
■const p = new Promise(function () {})
○promise 对象可以触发的两个方法
■p.then(函数); 成功时执行
■p.catch(函数); 失败时执行
●promise 封装一个异步函数
● 封装 promise 为函数
●promise 的链式调用
●promise 的调用方式补充
○如果你在第一个 then 里面返回(return) 一个新的 promise 对象的时候
○可以在第一个 then 后面, 继续第二个 then
●promise 的其他方法
●Promise 实例的 finally 方法
○不管promise是成功还是失败, 只要 promise 执行结束, 我都会执行
● Promise 本身还有一些方法
○all:
■作用: 可以同时触发多个 promise 行为
●只有所有的 promise 都成功的时候, all 才算成功
●只要任何一个 promise 失败的时候, all 就算失败了
■语法: Promise.all([多个 promise])
○race:
■作用: 可以同时触发多个 promise 行为
●按照速度计算, 当第一个结束的时候就结束了, 成功或失败取决于第一个执行结束的 promise
■语法: Promise.race([多个 promise])
○allSettled
■作用: 可以同时触发多个 Promise 行为
●不管多个成功还是失败都会触发
●会在结果内以数组的形式给你返回 每一个 promise 行为的成功还是失败
■语法: Promise.allSettled([多个 promise])
○resolve
■作用: 强制返回一个成功状态的 promise 对象
○reject
■作用: 强制返回一个失败状态的 promise 对象
●async / await
上述我们已经把 promise 的基础使用掌握了, 但是个人认为, promise 的链式调用仍然会有点小问题
就是在使用的时候, 过多的链式调用, 对于阅读体验来说, 仍然是有一点小问题, 不利于阅读
所以我们可以 使用 ES6+ 新推出的 async与await, 使用我的异步代码书写的更像是同步代码一样
●注意: 需要配合的必须是 Promise
●async 关键字的用法:
○直接书写在函数的前面即可, 表示该函数是一个异步函数
○意义: 表示在该函数内部可以使用 await 关键字
●await 关键字的用法:
○必须书写在一个有 async 关键字的函数内
○await 后面等待的内容必须是一个 promise 对象
○本该使用 then 接受的结果, 可以直接定义变量接受了
●常规的 promise 调用方式
●利用 async 和 await 关键字来使用
●async 和 await 语法的缺点
○await 只能捕获到 Promise 成功的状态
○如果失败, 会报错并且终止程序的继续执行
● 解决方法1: 使用 try...catch...
○语法: try { 执行代码 } catch (err) { 执行的代码 }
○首先执行 try 内部的代码, 如果不报错, catch 的代码不执行了
○如果报错, 不会爆出错误, 不会终止程序, 而是执行 catch 的代码, 报错信息在 catch 函数的形参内
●解决方法2: 改变封装的思路
○原因: 因为 promise 对象有成功和失败的状态, 所以会在失败状态是报错
○解决: 封装一个 百分比成功的 promise 对象, 让成功和失败的时候都按照 resolve 的形式来执行
○只不过传递出去的参数, 记录一个表示成功或者失败的信息
●封装 ajax
1.ajax 封装解析
a.封装方案
i.选择回调函数
1.将来使用的时候需要按照回调函数的语法使用
2.但是容易出现回调地狱
ii.选择 promise 的形式
1.按照 Promise 的形式来使用
2.后续可以利用 async/await 语法进一步简化代码
b.决定参数
i. 请求地址(url): 必填
ii.请求方式(method): 选填, 默认 GET
iii.是否异步(async): 选填, 默认 true 异步
iv.携带的参数(data): 选填, 默认 '' 空字符
c.决定返回值
i.需要
ii.返回一个 promise 对象
1.因为需要依赖返回值来决定使用 then 还是 catch
d.参数书写顺序
i.因为有多个参数, 并且有些参数可以有默认值
ii.所以我们只能通过传递一个对象的方式去处理
2.ajax 封装参数验证
3.ajax 封装默认值
4.ajax 封装发送请求
5.ajax 封装请求头信息
6.ajax 封装解析参数
7.ajax 封装基准地址
8.完整版 ajax 封装代码