Promise

241 阅读4分钟

1. 概念

  • 1.Promise是ES6引入的进行异步编程的新的解决方案 注:旧的方案是单纯地使用回调函数
  • 2.从语法上说:Promise是一个构造函数,用来生成Promise实例
  • 3.从功能上说:Promise对象用来封装一个异步操作并可以获取其成功或失败的结果值
  • 4Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolvereject
  • (1) resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”
  • (2) reject函数的作用是,将Promise对象的状态从“未完成”变为“失败” 一个 Promise 必然处于以下几种状态之一:
    Promise的状态:实例对象中的一个属性 PromiseState
    说明:一个Promise对象只能改变一次
  • 待定(pending) : 初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled) : 意味着操作成功完成。
  • 已拒绝(rejected) : 意味着操作失败。
// promise对象的值
// 实例对象中的另一个属性 PromiseResult
// 保存着异步任务成功或失败的结果
// resolve、reject函数可以对 PromiseResult的值进行修改赋值

image.png


const promise = new Promise(function(resolve, reject) {
      // 逻辑
      // 同步执行 【即 promise对象创建后,立即执行】
      if('异步操作成功') {
        resolve(value)  // 成功的回调
      } else {
        reject(error)   // 失败的回调
      }
});

// `Promise`实例生成以后,可以用`then`方法分别指定`resolved`状态和`rejected`状态的回调函数。
// 不管`promise`最后的状态,在执行完`then`或`catch`指定的回调函数以后,都会执行`finally`方法指定的回调函数。
    
    myPromise
    .then(
        (resolve) => {

        },
        (reject) => {

        }
    ).catch(error => {

    }).finally(() => {

    })

2. Promise基本流程

image.png

3. promise优点

支持链式调用,可以解决回调地狱问题

  • 1.回调地狱:回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件
  • 2.回调地狱的缺点:不便于阅读,不便于异常处理
    const doSomething = (doIt) => {
      // console.log('doIt', doIt)
      setTimeout(() => {
        console.log('doSomething')
        return doIt('doSomething')
      }, 500);
    }
    const doSomethingElse = (result, doIts) => {
      setTimeout(() => {
        console.log('doSomethingElse', result)
        return doIts('doSomethingElse')
      }, 500);
    }
    const doThirdThing = (newResult, doTest) => {
      setTimeout(() => {
        console.log('doThirdThing', newResult)
        return doTest('finally')
      }, 500);
    }

    doSomething(function(result) {
      doSomethingElse(result, function(newResult) {
        doThirdThing(newResult, function(finalResult) {
          console.log('得到最终结果: ' + finalResult);
        });
      });
    });
    // 输出:doSomething
    //      doSomethingElse doSomething
    //      doThirdThing doSomethingElse
    //      得到最终结果: finally

// 上述代码就是典型的异步回调。
// 通过`Promise`的改写上面的代码
    const doSomething = new Promise((resolve) => {
      resolve('doSomething')
    })
    const doSomethingElse = (result) => {
      return new Promise((resolve, reject) =>
      {
        setTimeout(() => {
          resolve('doSomethingElse')
            console.log('doSomethingElse', result)
          }, 500);
        })
    }
    const doThirdThing = (newResult) => {
        return new Promise((resolve, reject)=> {
          setTimeout(() => {
            resolve('doThirdThing')
            console.log('doThirdThing', newResult)
          }, 500);
        })
    }
    const failureCallback = new Promise((resolve, reject) => {
      return setTimeout(() => {
          resolve()
          console.log('failureCallback')
      }, 500)
    })

    doSomething.then(function(result) {
      return doSomethingElse(result);
    })
    .then(function(newResult) {
      return doThirdThing(newResult);
    })
    .then(function(finalResult) {
      console.log('得到最终结果: ' + finalResult);
    })
    // 打印输出:
    //         failureCallback
    //         doSomethingElse doSomething
    //         doThirdThing doSomethingElse
    //         得到最终结果: doThirdThing

// promise解决异步操作的优点
// -   链式操作减低了编码难度
// -   代码可读性明显增强

4. Promise构建出来的实例存在以下方法:(实例方法)

  • then()
  • catch()
  • finally()
    promise
    .then(result => {···})
    .catch(error => {···})
    .finally(() => {···});

5. 构造函数方法

  • all()
  • race()
  • allSettled()
  • resolve()
  • reject()
    // `Promise.all()`方法用于将多个 `Promise`实例,包装成一个新的 `Promise`实例
    // 接受一个数组(迭代对象)作为参数,数组成员都应为`Promise`实例
    const p = Promise.all([p1, p2, p3]);
    // 实例`p`的状态由`p1`、`p2`、`p3`决定,分为两种:
    //  -   只有`p1`、`p2`、`p3`的状态都变成`fulfilled`,`p`的状态才会变成`fulfilled`,此时`p1`、`p2`、`p3`的返回值组成一个数组,传递给`p`的回调函数
    // -   只要`p1`、`p2`、`p3`之中有一个被`rejected`,`p`的状态就变成`rejected`,此时第一个被`reject`的实例的返回值,会传递给`p`的回调函数
    const e1 = new Promise((resolve, reject) => {
      resolve('e1')
    })
    const e2 = new Promise((resolve, reject) => {
      resolve('e2')
    })
    const e3 = new Promise((resolve, reject) => {
      resolve('e3')
    })
    const p4 = Promise.all([e1, e2, e3])
    console.log(p4)
    // 控制台输出:
    Promise {<pending>}
      [[Prototype]]: Promise
      [[PromiseState]]: "fulfilled"
      [[PromiseResult]]: Array(3)
      
      
    const e1 = new Promise((resolve, reject) => {
      resolve('e1')
    })
    const e2 = new Promise((resolve, reject) => {
      reject('e2')
    })
    const e3 = new Promise((resolve, reject) => {
      reject('e3')
    })
    const p4 = Promise.all([e1, e2, e3])
    console.log(p4)
    // 控制台输出:
    Promise {<pending>}
        [[Prototype]]: Promise
        [[PromiseState]]: "rejected"
        [[PromiseResult]]: "e2"
    // `Promise.race()`方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例
    const p = Promise.race([p1, p2, p3]);
    // 只要`p1`、`p2`、`p3`之中有一个实例率先改变状态,`p`的状态就跟着改变 
    // 率先改变的 Promise 实例的返回值则传递给`p`的回调函数
    
    const p = Promise.race([
      new Promise(function (resolve, reject) {
        setTimeout(() => reject(new Error('request timeout...')), 500)
      }),
      new Promise(function (resolve, reject) {
        setTimeout(() => resolve('ok'), 500)
      })
    ]);

    p
    .then(console.log)
    .catch(console.error);
    // 控制台输出: Error: request timeout...
    // allSettled()
    // `Promise.allSettled()`方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例
    // 只有等到所有这些参数实例都返回结果,不管是`fulfilled`还是`rejected`,包装实例才会结束
    // resolve方法是函数对象的方法,并不是实例对象的方法(then,catch,finally)
    // 接受一个参数,并返回一个成功、失败的promise对象
    const p1 = Promise.resolve('todo')
    // (1) resolve方法中传入的参数为 非promise类型的对象时,则返回的结果为成功Promise对象
    console.log(p1)

    // (2) resolve方法中传入的参数为p romise类型的对象时,参数的结果决定了 resolve 的结果
    const p2 = Promise.resolve(new Promise((resolve, reject) => {
      // resolve('ok')
      reject('error')
    }))
    console.log(p2)
    p2.catch(reason => {
      console.log(reason)
    })
     // reject 方法
     // 接受一个参数,并返回一个新的 Promise 实例,该实例的状态为rejected
    const p3 = Promise.reject('出错了')
    // 等同于
    // const p3 = new Promise((resolve, reject)=> {
    //   reject('出错了')
    // })

    console.log(p3)
    p3.catch(reason => {
      console.log(reason)
    })

image.png