一:为什么需要promise

传统通过ajax请求数据,需要在回调函数中层层嵌套回调,这种结构叫做回调地狱,不利于阅读和后期维护
Promise出现正好解决了回调地狱 。

二:Promise的基本使用

Promise是一个构造函数,通过new关键字实例化对象
语法:

  1. new Priomise((resolve reject)=> { })
  • Promise接收一个函数作为参数
  • 在参数函数中接收两个参数

参数一: resolve–>成功函数
参数二 :reject–>失败函数

三:Promise实例

Promise实例有两个属性 :

  • state:状态
  • result:结果

    打印Promise实例:

    1. <body>
    2. <script>
    3. const p = new Promise((resolve, reject) => {})
    4. console.log(p)
    5. </script>
    6. </body>

    image.png

    1:Promise的状态

    第一种状态:pending(准备,带解决,进行中)
    第二种状态:fulfilled(已完成,成功)
    第三种状态:rejected(已拒绝,失败

    2:Promise状态的改变

    通过调用resolve()和reject()改变当前Promise对象的状态 :
    resolve():调用函数,使当前promise对象的状态改变成fulfilled
    reject():调用函数,使当前promise对象的状态改变成rejected
    Promise状态的改变是一次性的。

    调用resolve()函数并输出结果:

    1. <body>
    2. <script>
    3. const p = new Promise((resolve, reject) => {
    4. //resolve():调用函数,使当前promise对象的状态改变成fulfilled
    5. resolve()
    6. })
    7. console.log(p)
    8. </script>
    9. </body>

    image.png

    调用reject()函数并输出结果:

    1. <body>
    2. <script>
    3. const p = new Promise((resolve, reject) => {
    4. //reject():调用函数,使当前promise对象的状态改变成rejected
    5. reject()
    6. })
    7. console.log(p)
    8. </script>
    9. </body>

    image.png
    同时调用resolve()和reject()函数并输出结果:

    1. <body>
    2. <script>
    3. const p = new Promise((resolve, reject) => {
    4. //同时调用reject()和resolve(),对promise状态的改变是一次性的;
    5. //并不会reject()修改状态为rejected,再调用resolve()后把状态从rejected修改为fulfilled
    6. //reject()先行,所以状态一次性改为rejected
    7. reject()
    8. resolve()
    9. })
    10. console.log(p)
    11. </script>
    12. </body>

    image.png

    3:Promise的结果

    1、通过调用resolve(),传递参数,改变当前Promise对象的结果 :

    1. body>
    2. <script>
    3. const p = new Promise((resolve, reject) => {
    4. resolve('成功的结果')
    5. })
    6. console.log(p)
    7. </script>
    8. </body>

    image.png
    2、通过调用reject(),传递参数,改变当前Promise对象的结果 :

    1. <body>
    2. <script>
    3. const p = new Promise((resolve, reject) => {
    4. reject('失败的结果')
    5. })
    6. console.log(p)
    7. </script>
    8. </body>

    image.png

    三:Promise的方法

    1:then()方法

    then()方法是存在于Promise原型上的一个方法
    then()方法同时也是一个函数,有两个参数:
    1、是一个函数
    2、还是一个函数
    返回值:是一个新的Promise对象,而且此时状态还是pending

    1. <body>
    2. <script>
    3. const p = new Promise((resolve, reject) => {
    4. reject('失败的结果')
    5. })
    6. //p.then()返回值还是一个Promise对象
    7. const t = p.then(() => {
    8. console.log('成功时调用')
    9. }, () => {
    10. console.log('失败时调用')
    11. })
    12. console.log(t)
    13. </script>
    14. </body>

    image.png
    当promise的状态是fulfilled时,执行第一个参数函数体的内容;当promise的状态是rejected时,执行第二个参数函数体的内容。

对于为什么在then()方法的参数函数中,可以通过形参使用promise对象的结果呢?以下这张图是自己一些简单理解:
90909fb4308b40c6b3e6b8ac1baa0b81.png
Promise的状态不改变,不会执行then里的方法。

在then()方法中,通过return将返回的promise实例改为fulfilled状态。

  1. <body>
  2. <script>
  3. const p = new Promise ((resolve, reject) => {
  4. //1、使用resolve()回调,修改p实例化对象的状态为fulfilled,
  5. //从而会执行p.then()中第一个参数函数体内容
  6. resolve()
  7. })
  8. const t = p.then((value) => {
  9. console.log('成功')
  10. //2、使用return可以将t实例化对象的状态改变成fulfilled,
  11. //从而会执行t.then()中第一个参数函数体内容
  12. return 123
  13. }, (reason) => {
  14. console.log('失败')
  15. })
  16. t.then((value) => {
  17. //3、执行console.log('成功2', value)
  18. console.log('成功2', value)
  19. }, (reason) => {
  20. console.log('失败2')
  21. })
  22. </script>
  23. </body>

image.png
如果在then()方法的第一个参数函数中,出现代码错误,会将返回的Promise实例的状态改变成rejected:

  1. <body>
  2. <script>
  3. const p = new Promise ((resolve, reject) => {
  4. //1、使用resolve()回调,修改p实例化对象的状态为fulfilled,
  5. //从而会执行p.then()中第一个参数函数体内容
  6. resolve()
  7. })
  8. const t = p.then((value) => {
  9. console.log('成功')
  10. //2、这里代码出错,会将t实例化对象的状态改变成rejected
  11. console.log(a)
  12. }, (reason) => {
  13. console.log('失败')
  14. })
  15. t.then((value) => {
  16. console.log('成功2', value)
  17. //3、执行console.log('失败2', reason)
  18. }, (reason) => {
  19. console.log('失败2', reason)
  20. })
  21. </script>
  22. </body>

image.png

2:catch()方法

catch中参数函数在什么时候被执行?
1、当Promise的状态改为rejected时,被执行:

  1. <body>
  2. <script>
  3. const p = new Promise ((resolve, reject) => {
  4. reject()
  5. })
  6. p.catch((reason) => {
  7. console.log('失败', reason)
  8. })
  9. </script>
  10. </body>

image.png
2、当Promise执行体中出现代码错误时,被执行

  1. <body>
  2. <script>
  3. const p = new Promise ((resolve, reject) => {
  4. console.log(a)
  5. })
  6. p.catch((reason) => {
  7. console.log('失败', reason)
  8. })
  9. </script>
  10. </body>

image.png

四:使用Promise解决回调地狱

  1. <body>
  2. <script>
  3. //传统发送ajax请求,层层嵌套-->回调地狱
  4. $.ajax({
  5. type: 'GET',
  6. url: './data1.json',
  7. success: function (res) {
  8. const {id} = res
  9. $.ajax({
  10. type: 'GET',
  11. url: './data2.json',
  12. data: {id},
  13. success: function (res) {
  14. const {username} = res
  15. $.ajax({
  16. type: 'GET',
  17. url: './data3.json',
  18. data: { username },
  19. success: function (res) {
  20. console.log(res)
  21. //最终成功打印输出:"SWK@123456.com"
  22. }
  23. })
  24. }
  25. })
  26. }
  27. })
  28. //使用Promise解决回调地狱
  29. new Promise((resolve, reject) => {
  30. $.ajax({
  31. type: 'GET',
  32. url: 'data1.json',
  33. success: function (res) {
  34. //调用resolve(),保存从ajax返回数据res,并作为promise的结果,同时修改状态为fulfilled
  35. resolve(res)
  36. },
  37. error: function (res) {
  38. //修改promise的状态为rejected,修改promise的结果res
  39. reject(res)
  40. }
  41. })
  42. }).then((data) => {
  43. //对象解构
  44. const { id } = data
  45. return new Promise((resolve, reject) => {
  46. $.ajax({
  47. type: 'GET',
  48. url: 'data2.json',
  49. data: { id },
  50. success: function (res) {
  51. //调用resolve(),保存从ajax返回数据res,并作为promise的结果,同时修改状态为fulfilled
  52. resolve(res)
  53. },
  54. error: function (res) {
  55. //修改promise的状态为rejected,修改promise的结果res
  56. reject(res)
  57. }
  58. })
  59. })
  60. }).then((data) => {
  61. //对象解构
  62. const { username } = data
  63. return new Promise((resolve, reject) => {
  64. $.ajax({
  65. type: 'GET',
  66. url: 'data3.json',
  67. data: { username },
  68. success: function (res) {
  69. //调用resolve(),保存从ajax返回数据res,并作为promise的结果,同时修改状态为fulfilled
  70. console.log(res)
  71. //最终成功打印输出:"SWK@123456.com"
  72. }
  73. })
  74. })
  75. })
  76. </script>
  77. </body>

优化代码:

  1. <body>
  2. <script>
  3. function getData(url, data = {}) {
  4. return new Promise((resolve, reject) => {
  5. $.ajax({
  6. type: 'GET',
  7. url: url,
  8. data: data,
  9. success: function (res) {
  10. //调用resolve(),保存从ajax返回数据res,并作为promise的结果,同时修改状态为fulfilled
  11. resolve(res)
  12. },
  13. error: function (res) {
  14. //修改promise的状态为rejected,修改promise的结果res
  15. reject(res)
  16. }
  17. })
  18. })
  19. }
  20. getData('data1.json')
  21. .then((data) => {
  22. //对象解构
  23. const { id } = data
  24. return getData('data2.json', { id })
  25. })
  26. .then((data) => {
  27. //对象解构
  28. const { username } = data
  29. return getData('data3.json', { username })
  30. })
  31. .then((data) => {
  32. console.log(data)
  33. })
  34. </script>
  35. </body>