Promise使用详解

1 异步代码的困境

2 认识Promise作用

3 Promise基本使用

4 Promise状态变化

5 Promise实例方法

6 Promise的类方法

异步处理代码的困境

找以前的异步代码都是通过以下的方式封装的,有个缺点就是每个人写的execCode的参数顺序不一样,使用者可能会出现报错什么的,而且主要写的东西也是非常多。

   // 1.设计这样的一个函数
    function execCode(counter, successCallback, failureCallback) {
      // 异步任务
      setTimeout(() => {
        if (counter > 0) { // counter可以计算的情况 
          let total = 0
          for (let i = 0; i < counter; i++) {
            total += i
          }
          // 在某一个时刻只需要回调传入的函数
          successCallback(total)
        } else { // 失败情况, counter有问题
          failureCallback(`${counter}值有问题`)
        }
      }, 3000)
    }

    // 2.ES5之前,处理异步的代码都是这样封装
    execCode(100, (value) => {
      console.log("本次执行成功了:", value)
    }, (err) => {
      console.log("本次执行失败了:", err)
    })

Promise解决异步处理

1

  function execCode(counter) {
      const promise = new Promise((resolve, reject) => {
        // 异步任务
        setTimeout(() => {
          if (counter > 0) { // counter可以计算的情况 
            let total = 0
            for (let i = 0; i < counter; i++) {
              total += i
            }
            // 成功的回调
            resolve(total)
          } else { // 失败情况, counter有问题
            // 失败的回调
            reject(`${counter}有问题`)
          }
        }, 3000)
      })
      
      return promise
    }


    // const promise = execCode(100)
    // promise.then((value) => {
    //   console.log("成功有了结果: ", value)
    // })
    // promise.catch((err) => {
    //   console.log("失败有了错误: ", err)
    // })

    // const promise2 = execCode(-100)
    // promise2.then(value => {
    //   console.log("成功:", value)
    // })
    // promise2.catch(err => {
    //   console.log("失败:", err)
    // })

    // 执行一次
    execCode(255).then(value => {
      console.log("成功:", value)
    }).catch(err => {
      console.log("失败:", err)
    })

Promise各个状态区分

1

  // 1.创建一个Promise对象
    const promise = new Promise((resolve, reject) => {
      // 注意: Promise的状态一旦被确定下来, 就不会再更改, 也不能再执行某一个回调函数来改变状态
      // 1.待定状态 pending
      console.log("111111")
      console.log("222222")
      console.log("333333")

      // 2.兑现状态 fulfilled
      resolve()

      // 3.拒绝状态 rejected
      reject()
    })

    promise.then(value => {
      console.log("成功的回调")
    }).catch(err => {
      console.log("失败的回调")
    })

    // executor
    const promise2 = new Promise((resolve, reject) => {

    })

Promise的resolve的值

1

 const p = new Promise((resolve) => {
      // setTimeout(resolve, 2000)
      setTimeout(() => {
        resolve("p的resolve")
      }, 2000)
    })

    const promise = new Promise((resolve, reject) => {
      // 1.普通值
      // resolve([
      //   {name: "macbook", price: 9998, intro: "有点贵"},
      //   {name: "iPhone", price: 9.9, intro: "有点便宜"},
      // ])

      // 2.resolve(promise)
      // 如果resolve的值本身Promise对象, 那么当前的Promise的状态会有传入的Promise来决定
      // resolve(p)

      // 3.resolve(thenable对象)
      resolve({
        name: "kobe",
        then: function(resolve) {
          resolve(11111)
        }
      })
    })

    promise.then(res => {
      console.log("then中拿到结果:", res)
    })

Promise的then方法调度

1

   const promise = new Promise((resolve, reject) => {
      resolve("success")
      // reject("failure")
    })

    // promise.then(res => {
    // }).catch(err => {
    // })

    // 1.then参数的传递方法: 可以传递两个参数
    // 这种写法也是可以的
    // promise.then(res => {
    //   console.log("成功回调~", res)
    // }, err => {
    //   console.log("失败回调~", err)
    // })

    promise.then(res => {
      console.log("成功回调~", res)
    })
    promise.then(res => {
      console.log("成功回调~", res)
    })
    promise.then(res => {
      console.log("成功回调~", res)
    })
    promise.then(res => {
      console.log("成功回调~", res)
    })

Promise的catch方法调度

1

 const promise = new Promise((resolve, reject) => {
      reject("failure")
    })

    promise.then(res => {
      console.log("成功的回调:", res)
    }).catch(err => {
      console.log("失败的回调:", err)
    })

    promise.catch(err => {
      console.log("失败的回调:", err)
    })
    promise.catch(err => {
      console.log("失败的回调:", err)
    })
    promise.catch(err => {
      console.log("失败的回调:", err)
    })
    promise.catch(err => {
      console.log("失败的回调:", err)
    })

Promise的then的返回值

then的返回值是新的promise,连续的.then是上一个then的返回值,不同于promise的调度方法

 const promise = new Promise((resolve, reject) => {
      resolve("aaaaaaa")
      // reject()
    })

    // 1.then方法是返回一个新的Promise, 这个新Promise的决议是等到then方法传入的回调函数有返回值时, 进行决议
    // Promise本身就是支持链式调用
    // then方法是返回一个新的Promise, 链式中的then是在等待这个新的Promise有决议之后执行的
    // promise.then(res => {
    //   console.log("第一个then方法:", res)
    //   return "bbbbbbbb"
    // }).then(res => {
    //   console.log("第二个then方法:", res)
    //   return "cccccccc"
    // }).then(res => {
    //   console.log("第三个then方法:", res)
    // })

    // promise.then(res => {
    //   console.log("添加第二个then方法:", res)
    // })

    // 2.then方法传入回调函数的返回值类型
    const newPromise = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("why")
      }, 3000)
    })

    promise.then(res => {
      console.log("第一个Promise的then方法:", res)
      // 1.普通值
      // return "bbbbbbb"
      // 2.新的Promise
      // return newPromise
      // 3.thenable的对象
      return {
        then: function(resolve) {
          resolve("thenable")
        }
      }
    }).then(res => {
      console.log("第二个Promise的then方法:", res) // undefined
    })

Promise的catch的返回值

catch后面返回的也是promise,也可以通过then拿到返回值。

只要promise先决议的是resolve,不管有多少个then,then全部都执行,catch不会执行;

只要promise先决议reject,不管catch前面有多少个then都不会执行,就马上执行catch里面的内容。

可以通过抛出异常来进入catch,如果抛出异常后没有catch会报错。

 const promise = new Promise((resolve, reject) => {
      // reject("error: aaaaa")
      resolve("aaaaaa")
    })

    // 1.catch方法也会返回一个新的Promise
    // promise.catch(err => {
    //   console.log("catch回调:", err)
    //   return "bbbbb"
    // }).then(res => {
    //   console.log("then第一个回调:", res)
    //   return "ccccc"
    // }).then(res => {
    //   console.log("then第二个回调:", res)
    // })

    // 2.catch方法的执行时机
    promise.then(res => {
      console.log("then第一次回调:", res)
      // throw new Error("第二个Promise的异常error") 
      return "bbbbbb"
    }).then(res => {
      console.log("then第二次回调:", res)
      throw new Error("第三个Promise的异常error")
    }).then(res => {
      console.log("then第三次回调:", res)
    }).catch(err => {
      console.log("catch回调被执行:", err)
    })

    // 中断函数继续执行:
    // 方式一: return
    // 方式二: throw new Error()
    // 方式三: yield 暂停(暂时性的中断)

Promise的finally的回调

兜底方法,执行过then或者catch之后一定会执行的方法。

 const promise = new Promise((resolve, reject) => {
      // pending

      // fulfilled
      resolve("aaaa")

      // rejected
      // reject("bbbb")
    })

    promise.then(res => {
      console.log("then:", res)
      // foo()
    }).catch(err => {
      console.log("catch:", err)
      // foo()
    }).finally(() => {
      console.log("哈哈哈哈")
      console.log("呵呵呵呵")
    })


    function foo() {
      console.log("哈哈哈哈")
      console.log("呵呵呵呵")
    }

Promise类方法-resolve

实例方法是不要要创建实例对象才能使用的,new xxx的实例对象。

类方法是单独类名.xxx方法就能直接使用。

如果单纯需要拿个异步的某个参数,可以直接写类方法来简化代码。

 // 实例方法
    // const promise = new Promise((resolve) => {
    //   // 进行一系列的操作
    //   resolve("result")
    // })
    // promise.catch

    // 类方法
    const studentList = []
    const promise = Promise.resolve(studentList)

    promise.then(res => {
      console.log("then结果:", res)
    })
    // 相当于
    // new Promise((resolve) => {
    //   resolve("Hello World")
    // })

Promise类方法-reject

1

 // 类方法
    const promise = Promise.reject("rejected error")
    promise.catch(err => {
      console.log("err:", err)
    })
    // 相当于 _表示resolve,这个位置一定不能变,因为promise就是2个参数,不要少写
    // new Promise((_, reject) => {
    //   reject("rejected error")
    // })

Promise类方法-all方法

需要等待前面多个promise都执行resolve完成之后在执行某个then的话使用all的then。同理如果all里面某个promise返回了reject的话,那all的then就执行不了了,会跳到all的catch

里面去执行。

 

 // 创建三个Promise
    const p1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        // resolve("p1 resolve")
        reject("p1 reject error")
      }, 3000)
    })

    const p2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("p2 resolve")
      }, 2000)
    })
    
    const p3 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("p3 resolve")
      }, 5000)
    })

    // all:全部/所有
    Promise.all([p1, p2, p3]).then(res => {
      console.log("all promise res:", res)
    }).catch(err => {
      console.log("all promise err:", err)
    })

Promise类方法-allSettled

这个是all方法的强化班,一定会执行then。会返回每个promise 的状态。

Promise使用详解_第1张图片

 

  // 创建三个Promise
    const p1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        // resolve("p1 resolve")
        reject("p1 reject error")
      }, 3000)
    })

    const p2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("p2 resolve")
      }, 2000)
    })
    
    const p3 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("p3 resolve")
      }, 5000)
    })

    // 类方法: allSettled
    Promise.allSettled([p1, p2, p3]).then(res => {
      console.log("all settled:", res)
    })

Promise类方法-race方法

拿来测试代码速度的一个办法,就是有多个promise的情况下,哪个执行快就then哪个出来。

缺点是不管是resolve还是reject先输出,都会看成是完成了。

 // 创建三个Promise
    const p1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("p1 resolve")
        // reject("p1 reject error")
      }, 3000)
    })

    const p2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        // resolve("p2 resolve")
        reject("p2 reject error")
      }, 2000)
    })
    
    const p3 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("p3 resolve")
      }, 5000)
    })


    // 类方法: race方法
    // 特点: 会等到一个Promise有结果(无论这个结果是fulfilled还是rejected)
    Promise.race([p1, p2, p3]).then(res => {
      console.log("race promise:", res)
    }).catch(err => {
      console.log("race promise err:", err)
    })

Promise类方法-any方法

是race的优化版,只会将最先完成的resolve的结果输出

 // 创建三个Promise
    const p1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        // resolve("p1 resolve")
        reject("p1 reject error")
      }, 3000)
    })

    const p2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        // resolve("p2 resolve")
        reject("p2 reject error")
      }, 2000)
    })
    
    const p3 = new Promise((resolve, reject) => {
      setTimeout(() => {
        // resolve("p3 resolve")
        reject("p3 reject error")
      }, 5000)
    })

    // 类方法: any方法
    Promise.any([p1, p2, p3]).then(res => {
      console.log("any promise res:", res)
    }).catch(err => {
      console.log("any promise err:", err)
    })

Promise使用详解_第2张图片

Promise使用详解_第3张图片

Promise使用详解_第4张图片Promise使用详解_第5张图片

Promise使用详解_第6张图片 Promise使用详解_第7张图片

 Promise使用详解_第8张图片

 Promise使用详解_第9张图片

 Promise使用详解_第10张图片

 Promise使用详解_第11张图片

 Promise使用详解_第12张图片

 Promise使用详解_第13张图片

 Promise使用详解_第14张图片

 Promise使用详解_第15张图片

 Promise使用详解_第16张图片

 Promise使用详解_第17张图片

 Promise使用详解_第18张图片

 Promise使用详解_第19张图片

你可能感兴趣的:(javascript高级,前端,javascript,ecmascript)