• 【学习笔记72】 Promise和async 与 await


    一、Promise

    • 一个新的异步代码封装方案
    • 以前通过回调函数的形式去封装, 会导致出现回调地狱
    • 现在换promise 后, 就解决了这个问题

    1、promise 它会有三个状态

    • 持续: pending
    • 成功: fulfilled
    • 失败: rejected

    2、promise 只会发生两个转换

    • 持续 ==> 成功
    • 持续 ==> 失败

    3、promise实例化对象的方法

    • .then
    • .catch

    4、代码的实现

    1. const p = new Promise(function (resolve, reject) {
    2. /**
    3. * resolve 会把我们这个 promise 状态转换为 成功
    4. * reject 会把我们这个 promise 状态转换为 失败
    5. *
    6. * 这两个 都是 函数
    7. */
    8. console.log('班长帮我去买一瓶水')
    9. const timer = Math.ceil(Math.random() * 3000) + 2000
    10. setTimeout(() => {
    11. if (timer > 3500) {
    12. console.log('班长买水失败', timer)
    13. reject('班长买水失败, 再换个地方买')
    14. } else {
    15. console.log('班长买水成功', timer)
    16. resolve('班长买水成功, 奖励二十个bug')
    17. }
    18. }, timer)
    19. })
    20. p.then(function (res) {
    21. // promise 成功状态时触发
    22. //并且接受resolve时传递的参数
    23. console.log(res);
    24. })
    25. p.catch(function (res) {
    26. // promise失败状态时触发
    27. // 并且接受reject时传递的参数
    28. console.log(res);
    29. })

    5、promise实例化对象可以接受链式调用

    1. const p = new Promise(function (resolve, reject) {
    2. console.log('班长帮我去买一瓶水')
    3. const timer = Math.ceil(Math.random() * 3000) + 2000
    4. setTimeout(() => {
    5. if (timer > 3500) {
    6. console.log('班长买水失败', timer)
    7. reject('班长买水失败, 再换个地方买')
    8. } else {
    9. console.log('班长买水成功', timer)
    10. resolve('班长买水成功, 奖励二十个bug')
    11. }
    12. }, timer)
    13. })
    14. p.then(function (res) {
    15. console.log(res)
    16. }).catch(function (res) {
    17. console.log(res)
    18. })

    二、封装promise

    • promise.then内部return了一个新的 promise对象
    • 可以在后续再写几个 .then
    1. function fn() {
    2. const p = new Promise(function (resolve, reject) {
    3. const timer = Math.ceil(Math.random() * 3000) + 2000
    4. setTimeout(() => {
    5. if (timer > 3500) {
    6. reject('班长买水失败, 再换个地方买')
    7. } else {
    8. resolve('班长买水成功, 奖励二十个bug')
    9. }
    10. }, timer)
    11. })
    12. return p
    13. }
    14. fn().then((res) => {
    15. console.log('班长第一次买水成功')
    16. return fn()
    17. }).then((res) => {
    18. console.log('班长第二次买水成功')
    19. return fn()
    20. }).then((res) => {
    21. console.log('班长第三次买水成功')
    22. }).catch((res) => {
    23. console.log('班长买水失败')
    24. })

    三、async 与 await

    • 作用: 能帮助我们把异步代码, 写的和同步代码一样
    1. function fn() {
    2. const p = new Promise(function (resolve, reject) {
    3. const timer = Math.ceil(Math.random() * 3000)
    4. setTimeout(() => {
    5. if (timer > 3500) {
    6. reject('班长真好, 就是买水失败, 再换个地方买')
    7. } else {
    8. resolve('班长真好, 就是买水成功, 奖励二十个bug')
    9. }
    10. }, timer)
    11. })
    12. return p
    13. }
    14. // 1. 函数开头必须书写async表明内部可以书写await
    15. async function newFn() {
    16. /**
    17. * await 后边需要跟着promise
    18. * await表示等到的意思, 执行到fn(),虽然是异步的
    19. * 但是因为有await关键字, 此时不会往下继续执行,
    20. * 而是等待 fn()执行完毕, 在往下执行
    21. */
    22. let r1 = await fn()
    23. console.log(r1)
    24. // console.log('如果失败了, 执行这行代码, 提示用户网络有问题')
    25. }
    26. newFn()

    四、async与await的问题

    • 没有办法捕获到错误, 只能接受promise的成功状态
    • 如果报错, 会中断程序执行

    解决方法1: try...catch

    • 首次执行的时候,会走try这个分支, 如果这个位置有报错
    • 他会结束执行try分支, 然后走catch分支
    • 如果再运行try分支的时候, 没有报错, 那么catch不会运行
    1. function fn() {
    2. const p = new Promise(function (resolve, reject) {
    3. const timer = Math.ceil(Math.random() * 3000) + 2000
    4. setTimeout(() => {
    5. if (timer > 3500) {
    6. reject('班长真好, 就是买水失败, 再换个地方买')
    7. } else {
    8. resolve('班长真好, 就是买水成功, 奖励二十个bug')
    9. }
    10. }, timer)
    11. })
    12. return p
    13. }
    14. async function newFn() {
    15. try {
    16. let r1 = await fn()
    17. console.log(r1)
    18. } catch (error) {
    19. console.log(error)
    20. }
    21. }
    22. newFn()

    解决方法2: 更改 promise 的封装

    • 原因: promise执行reject时,async await不能捕获到错误,
    • 解决: 让这个promise不管什么情况都返回resolve,我们通过返回的参数, 区分现在时成功还是失败
    • 开发中,对象内的code如果为0, 一般代表失败;对象内的code如果为1, 一般代表成功
    1. function fn() {
    2. const p = new Promise(function (resolve, reject) {
    3. const timer = Math.ceil(Math.random() * 3000) + 1000
    4. setTimeout(() => {
    5. if (timer > 3500) {
    6. // reject('班长真好, 就是买水失败, 再换个地方买')
    7. resolve({
    8. code: 0,
    9. msg: '班长真好, 就是买水失败, 再换个地方买'
    10. })
    11. } else {
    12. resolve({
    13. code: 1,
    14. msg: '班长真好, 就是买水成功, 奖励二十个bug'
    15. })
    16. }
    17. }, timer)
    18. })
    19. return p
    20. }
    21. async function newFn() {
    22. let r1 = await fn()
    23. if (r1.code === 0) {
    24. console.log('您的网络有问题')
    25. } else {
    26. console.log(r1.msg)
    27. }
    28. }
    29. newFn()

    五、promise的其他方法

    (一)finally

    • promise 实例化对象还有一个方法(finally)
    1. function fn() {
    2. const p = new Promise(function (resolve, reject) {
    3. const timer = Math.ceil(Math.random() * 3000) + 2000
    4. setTimeout(() => {
    5. if (timer > 3500) {
    6. reject('失败')
    7. } else {
    8. resolve('成功')
    9. }
    10. }, timer)
    11. })
    12. return p
    13. }
    14. fn().then(res => {
    15. console.log('成功了: ', res)
    16. }).catch(res => {
    17. console.log('失败了: ', res)
    18. }).finally(res => {
    19. console.log('不管成功还是失败,都会执行')
    20. })

     (二)Promise构造函数上也有一些方法

    1、all

    • all接受一个数组, 数组内可以传递多个promise对象
    • all方法的状态取决数组内部的promise对象的状态
    • 如果都是成功, all方法也是成功
    • 如果有一个失败, all方法就是失败
    1. function fn() {
    2. const p = new Promise(function (resolve, reject) {
    3. const timer = Math.ceil(Math.random() * 3000) + 2000
    4. setTimeout(() => {
    5. if (timer > 3500) {
    6. reject('失败')
    7. } else {
    8. resolve('成功')
    9. }
    10. }, timer)
    11. })
    12. return p
    13. }
    14. Promise.all([fn(), fn(), fn()])
    15. .then(res => {
    16. console.log('如果我输出, 代表所有promise对象都是成功状态')
    17. })
    18. .catch(res => {
    19. console.log('如果我输出, 代表最少有一个promise状态为失败状态')
    20. })

    2、race

    • race接受一个数组, 数组内可以传递多个 promise 对象
    • race 方法的状态取决于,数组内部的 promise 对象中第一个结束
    • 如果第一个结束时是成功, race 就是成功
    • 如果第一个结束时时失败, race 就是失败
    1. function fn() {
    2. const p = new Promise(function (resolve, reject) {
    3. const timer = Math.ceil(Math.random() * 3000) + 2000
    4. setTimeout(() => {
    5. if (timer > 3500) {
    6. reject('失败')
    7. } else {
    8. resolve('成功')
    9. }
    10. }, timer)
    11. })
    12. return p
    13. }
    14. Promise.race([fn(), fn(), fn()])
    15. .then(res => {
    16. console.log('如果我执行, 代表数组内第一个结束的promise状态为成功')
    17. })
    18. .catch(res => {
    19. console.log('如果我执行, 代表数组内第一个结束的promise状态为失败')
    20. })

    3、allSettled

    • allSettled 接受一个数组, 数组内可以传递多个 promise
    • 只会执行 .then, 接收到的参数是一个数组形式的, 内部元素为对应的promise的状态
    1. function fn() {
    2. const p = new Promise(function (resolve, reject) {
    3. const timer = Math.ceil(Math.random() * 3000) + 2000
    4. setTimeout(() => {
    5. if (timer > 3500) {
    6. reject('失败')
    7. } else {
    8. resolve('成功')
    9. }
    10. }, timer)
    11. })
    12. return p
    13. }
    14. Promise.allSettled([fn(), fn(), fn(), fn()])
    15. .then(res => {
    16. console.log(res)
    17. })

    4、强行帮我们返回一个成功状态的 promise 对象

    1. function fn() {
    2. const p = new Promise(function (resolve, reject) {
    3. const timer = Math.ceil(Math.random() * 3000) + 2000
    4. setTimeout(() => {
    5. if (timer > 3500) {
    6. reject('失败')
    7. } else {
    8. resolve('成功')
    9. }
    10. }, timer)
    11. })
    12. return p
    13. }
    14. Promise.resolve()
    15. .then(res => {
    16. console.log('成功')
    17. }).catch(res => {
    18. console.log('失败')
    19. })

    5、强行帮我们返回一个失败状态的promise 对象

    1. function fn() {
    2. const p = new Promise(function (resolve, reject) {
    3. const timer = Math.ceil(Math.random() * 3000) + 2000
    4. setTimeout(() => {
    5. if (timer > 3500) {
    6. reject('失败')
    7. } else {
    8. resolve('成功')
    9. }
    10. }, timer)
    11. })
    12. return p
    13. }
    14. Promise.reject()
    15. .then(res => {
    16. console.log('成功')
    17. }).catch(res => {
    18. console.log('失败')
    19. })
  • 相关阅读:
    RuoYi-Vue的中小企业专业化、通用性、低成本的MES系统解决方案
    计算机组成原理--数据表示
    XC5VLX30T-2FF323I Virtex-5 LXT FPGA IC 产品参数
    2022华为杯研究生数学建模解题思路和代码思路
    Au:轨道种类及操作基础
    2022年字节跳动抖音日常实习面经
    算法训练day41|动态规划 part03(LeetCode343. 整数拆分、96.不同的二叉搜索树)
    数据结构与算法2-时间空间复杂度分析
    Python获取免费代理IP,并全部测试一遍,结果大失所望
    零基础安装分布式数据服务注册系统
  • 原文地址:https://blog.csdn.net/m0_58190023/article/details/128058135