Promise到底是个啥玩意

Promise到底是个啥玩意
1. 回调地域在学习 Promise 之前 , 我们先看一下什么是回调地狱:
这里我们模拟三个请求接口:

  1. 获取产品类别
// 1. 获取类别信息const getCategory = () => {// 模拟请求let res = {code: 200message: \"请求成功\"data: [{ id: 1 name: \"水果\"{ id: 2 name: \"图书\"
;return res;;
  1. 根据类别 id 获取产品信息
// 2. 根据类别 id 获取产品信息const getProductByCategoryId = (categoryId) => {// 模拟请求let res = {code: 200message: \"请求成功\"data: [{ id: 111 categoryId: 1 name: \"苹果\"{ id: 112 categoryId: 1 name: \"香蕉\"{ id: 113 categoryId: 1 name: \"百香果\"
;return res;;
  1. 根据产品 id 获取产品价格
// 3. 根据产品id获取产品价格const getPriceByProductId = (productId) => {// 模拟请求let res = {code: 200message: \"请求成功\"data: { id: 1001 productId: 111 price: 112.23 unitPrice: 1235.23;return res;;接下来我们去获取第一个类别下第一个产品的单位价格信息:
let unitPrice = 0.0;// 获取产品价格const getProductPrice = () => {let categoryRes = getCategory();if (categoryRes.code === 200) {let produceRes = getProductByCategoryId(1);if (produceRes.code === 200) {let priceRes = getPriceByProductId(1);if (priceRes.code === 200) {unitPrice = res.data.unitPrice;;我们发现在 getProductPrice 这个方法中 , 第一个请求接口的结果要作为第二个请求接口的参数 , 以此类推就会出现层层嵌套 , 回调里面套回调 , 这就是所谓的“回调地狱” 。
如果请求的接口太多 , 那代码写起来可就太苦逼了 , 就跟套娃一样 。

所以为了解决回调地狱的问题 , 提高代码的可读性 , Promise 应运而生 。
2. 邂逅 PromisePromise 是异步编程的一种解决方案 。 它本质上是一个构造函数 , 可以构建一个 Promise 对象 。
Promise 构造函数接受一个函数作为参数 , 该函数的两个参数分别是 resolve 和 reject。 对象上有 then、catch、finall 方法 。
Promise 有三种状态:pending、fulfilled、rejected:
  • pending:它的意思是待定的 , 相当于是一个初始状态 。 创建 Promise 对象时就是一个初始状态 。
  • fulfilled:成功 。 当调用 resolved 方法后 , Promise 对象的状态就会从 pending 切换到 fulfilled , 且不可改变 。
  • rejected:失败 。 当调用 reject 方法后 , Promise 对象的状态就会从 pending 切换到 reject , 且不可改变 。
看了上面的解释 , 你可能还是有点懵逼 , 接下来我用通俗易懂的语言解释一下 Promise 是个什么玩意:
1.Promise 就是一个用来封装 HTTP 请求的工具 。
2.我们请求后台接口获取数据 , 如果请求成功 , 就调用 Promise 的 resolve 方法 , 并将返回的数据作为该方法的参数 。 如果请求失败 , 就调用 Promise 的 reject 方法 , 并将返回的错误信息作为该方法的参数 。
3.然后我们将一个 Promise 对象作为该请求接口的返回值返回 。
4.因为该接口返回一个 Promise 对象 , 所以我们调用该接口的时候就可以直接用.then()处理成功的信息 , 用 .catch() 处理失败的信息了 。
接下来我们将上面的例子用 Promise 改造一下 , 有了真实案例 , 大家对 Promise 的理解就更清晰明了了 。
3. 使用 Promise
  1. 获取类别信息
const getCategory = () => {// 返回结果封装成 Promise 对象return new Promise((resolve reject) => {// 模拟请求let res = {code: 200message: \"请求成功\"data: [{ id: 1 name: \"水果\"
;if (res.code == 200) {resolve(res);else {reject(res););;
  1. 根据类别 id 获取产品信息
const getProductByCategoryId = (categoryId) => {return new Promise((resolve reject) => {// 模拟请求let res = {code: 200message: \"请求成功\"data: [{ id: 111 categoryId: 1 name: \"苹果\"{ id: 112 categoryId: 1 name: \"香蕉\"{ id: 113 categoryId: 1 name: \"百香果\"
;if (res.code == 200) {resolve(res);else {reject(res););;
  1. 根据产品 id 获取产品价格
const getPriceByProductId = (productId) => {return new Promise((resolve reject) => {// 模拟请求let res = {code: 200message: \"请求成功\"data: { id: 1001 productId: 111 price: 112.23 unitPrice: 1235.23;if (res.code == 200) {resolve(res);else {reject(res););;4.获取第一个类别下第一个产品的单位价格信息
Promise 最常用的就是链式调用格式:
let unitPrice = 0.0;// 获取产品价格const getProductPrice = () => {getCategory().then(res => {// 类别 idlet id = res.data[0
.id;// 返回一个 Promise 对象return getProductByCategoryId(id);).then(res => {// 产品 idlet id = res.data[0
.id;return getPriceByProductId(id);).then(res => {unitPrice = res.data.unitPrice;);
当然我们在日常使用过程中一般都是这种格式:
getMethod().then(res => {// 请求成功).catch(error=>{// 异常).finally(()=>{// 不管成功还是异常都要执行)4. async 和 await虽然有了 Promise 之后 , 代码的可读性有了很大提高 。 但是 ES7 又引入了 async 和 await 来简化 Promise 调用操作 , 实现了以异步操作像同步的方式去执行 。
说白了async 和 await 就是对 Promise 进行了封装 。
语法:
await 和 async 是成对出现的 , 如果写了 await 必须要写 async , 否则会报错 。 如果只写 async , 那返回的就是一个 Promise 对象
举例:
let unitPrice = 0.0;// 获取产品价格const getProductPrice = async () => {let res1 = await getCategory();let categoryId = res1.data[0
.id;let re2 = await getProductByCategoryId(categoryId);let productId = re2.data[0
.id;let re3 = await getPriceByProductId(productId);unitPrice = res3.data.unitPrice;;
如果只写 async返回的就是一个 Promise 对象
const getProductPrice = async () => {getCategory().then(res=>{let categoryId =res.data[0
.id);const getCategory = async () => {// 模拟请求let res = {code: 200message: \"请求成功\"data: [{ id: 1 name: \"水果\"{ id: 2 name: \"图书\"
;return res;;
那为什么说 async 和 await 实现了异步编程同步化呢?
因为 await 这个命令的意思就是等这一行的异步方法执行成功后 , 然后才能执行下一行代码 , 否则就一直等待 , 下面的代码就执行不了 。
所以虽然请求后台的接口是异步的 , 但是 await 在语法层面实现了同步 。
5. 答疑5.1 同步请求和异步请求同步请求:当发送一个同步请求时 , 会暂停后面的代码执行 , 等待请求的返回结果 , 然后再继续执行下一行代码 。
异步请求:当发送一个异步请求时 , 会继续执行后面的代码而不会等待请求的返回结果 。 当请求完成后 , 再通过回调函数或事件处理函数来处理返回的数据 。
1.同步请求就会依次打?。 ?、2 。 如果第一个方法执行时间比较长 , 那就一直等待 。
const getProductPrice =() => {console.log(\"1\");console.log(\"2\")2.异步请求可能会先打印 2 , 后打印 1 。
const getProductPrice = async() => {console.log(\"1\");console.log(\"2\")5.2 promise 和 axios 什么关系Promise 是 JavaScript 中用于异步编程的一个对象 , 而 axios 是 用来发送 HTTP 请求的工具库 。
Promise 对 axios 的返回结果进行了封装 。 所以当你发送一个 axios 请求 , 会返回一个 Promise 对象 。 然后你就可以调用 .then、.catch方法了 。
5.3 promise 和 async/await 什么关系1.async/await 对 promise 进行了封装 。
2.async/await 是用同步语法去获取异步请求 , 彻底消灭回调函数 。
3.只有 async , 返回的是 Promise 对象 。
【Promise到底是个啥玩意】4.await 相当于 Promise 的 then

    推荐阅读