什么是Promise呢?

  • 定义:Promise是ES6异步编程的解决方案
  • 那什么时候我们会处理异步事件呢?

    • 一种很常见的场景就是网络请求了
    • 我们封装一个网络请求的函数,因为不能立即拿到结果,而js代码又不能一直停在那里等
    • 所以我们往往会传入另外一个函数,在数据请求成功后,将数据通过传入的函数调出去
    • 如果一个简单的网络请求,可以使用这种方案,但是如果遇到异步的嵌套,就会出现回调地狱的问题,如下
      1. $.ajax('url1', function(data1) {
      2. $(data1['url2'], function (data2) {
      3. $(data2['url3'], function (data3) {
      4. $(data3['url4'], function (data4) {
      5. console.log(data4);
      6. })
      7. })
      8. })
      9. })
  • 如上代码难看且难以维护,我们可以使用Promise来解决这个问题

Promise的基本使用

  • 我们使用setTimeout来模拟一个异步事件
    • 一旦我们在Promise中调用了resolve()函数,就会来到.then()这个函数中
    • 在这个then()中,对第一个setTimeout中的内容进行处理,处理完成后,如果还要进行下一个异步处理,就return一个新的Promise
    • 这就成为了我们所说的链式编程 ```javascript setTimeout(() => { console.log(‘hello world’) }, 1000)

// 我们对如上异步操作进行封装,Promise中传入一个函数,其中两个参数resolve,reject也都是函数 new Promise((resole, reject) => { setTimeout(() => { resolve() }, 1000) }).then(() => { console.log(‘hello world’)

return new Promise ((resolve, reject) => { setTimeout(() => { resolve() }, 1000) }).then(() => { console.log(‘hello Vuejs’) }) })

  1. - 什么情况下会用到Promise?>异步操作的时候,当我们要用到异步操作时,直接把异步操作那一坨代码往Promise里面一塞就行了,resolve()中的内容就会被传递到.then()中的data参数中,这样就可以在.then 中使用该数据了
  2. - 当然,如果网络请求失败了,就调用reject( )方法,括号中传入错误信息即可,此时不会进入.then( )方法,而是会进入.catch( )方法,将我们reject( ) 括号中的内容传入到 .catch ( ) 方法中进行相关的处理
  3. <a name="qwu3h"></a>
  4. ## Promise 的三种状态
  5. - 当我们使用Promise时,异步操作就会出现三种状态
  6. - pending 等待状态,比如正在进行网络请求,或者定时器没有到时间
  7. - fulfill:完成状态,当我们主动调用了resolve时,就处于该状态,并且会回调.then( )
  8. - reject:拒绝状态,当我们主动调用了reject时,就处于该状态,并且会回调.catch( )
  9. <a name="hrUHr"></a>
  10. ## Promise 的链式调用
  11. - 对请求回来的结果进行链式的处理
  12. ```javascript
  13. new Promise((resolve, reject) => {
  14. setTimeout(() => {
  15. resolve('aaa')
  16. }, 1000)
  17. }).then(res => {
  18. console.log(res, '第一层代码')
  19. return new Promise(resolve => {
  20. resolve(res + '111')
  21. })
  22. }).then(res => {
  23. console.log(res, '第二层代码')
  24. return new Promise(resolve => {
  25. resolve(res + '222')
  26. })
  27. }).then(res => {
  28. console.log(res, '第三层代码')
  29. })
  • 对如上代码进行简化

    1. new Promise((resolve, reject) => {
    2. setTimeout(() => {
    3. resolve('aaa')
    4. }, 1000)
    5. }).then(res => {
    6. console.log(res, '第一层代码')
    7. return Promise.resolve(res + '111')
    8. }).then(res => {
    9. console.log(res, '第二层代码')
    10. return Promise.resolve(res + '222')
    11. }).then(res => {
    12. console.log(res, '第三层代码')
    13. })
  • 甚至还可以再简化,不用写Promise.resolve

    1. new Promise((resolve, reject) => {
    2. setTimeout(() => {
    3. resolve('aaa')
    4. }, 1000)
    5. }).then(res => {
    6. console.log(res, '第一层代码')
    7. return res + '111'
    8. }).then(res => {
    9. console.log(res, '第二层代码')
    10. return res + '222'
    11. }).then(res => {
    12. console.log(res, '第三层代码')
    13. })
  • 如果链式调用时,中间的一部分出现了错误,我们可以再链式最后面加上.catch( )方法来处理错误,在出现错误的地方通过return Promise reject(‘error message’)的方法抛出错误,或者通过throw ‘error message’ 的方式抛出错误,在最后面的catch方法都可以拿到这个错误

Promise 的all方法

  • 如果我们想要完成一个需求,而这个需求需要两个网络请求都完成才能完成,那么该如何实现呢?

    1. Promise.all([
    2. new Promise((resolve, reject) => {
    3. $ajax({
    4. url: 'url1',
    5. success: function (data) {
    6. resolve(data1)
    7. }
    8. })
    9. }),
    10. new Promise((resolve, reject) => {
    11. $ajax({
    12. url: 'url2',
    13. success: function (data) {
    14. resolve(data2)
    15. }
    16. })
    17. })
    18. ]).then(results => {
    19. console.log(results)
    20. })
  • 这样处理它内部就会判断,两个Promise都成功后才会执行后面的.then( )方法,且这个results中放的就是[data1, data2]