• promise的学习


    欢迎大家访问我的博客dreamITGirl,不要吝啬你们的小星星,点个star~ 有问题的话,你可以将问题在 GitHub问我.

    这篇文章是阅读完promiseA+规范和ES6入门教程,写的总结。

    Promise对象

    Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。

    术语

    1. promise : 是拥有then方法的对象或者函数

    2. thenable : 定义了then方法的对象或者函数

    3. value : 任何JS的合法值

    4. exception : 使用throw抛出的一个值

    5. reason : promise被拒绝的原因

    Promise的状态

    1. pending (等待) :promise初始化状态

    2. fulfilled (执行) : pending => resolve

    3. rejected (拒绝): pending => rejected

    Promise方法

    promise必须提供一个then的方法,来访问当前的最终值或者原因

    promise.then(onFulfilled,onRejected)
    
    1. onFulfilledonRejected都是可选的参数,
      如果有个不是函数的话,这个将会被忽略

      案例:

      const promise = new Promise((resolve,reject) => {
          if(/**异步执行成功**/){
              resolve(value)
          } else {
              resolve(error)
          }
      })
      
      
      function timeout(ms) {
          return new Promise((resolve, reject) => {
              setTimeout(resolve, ms, 'done');
          });
      }
      
      timeout(100).then((value) => {
          console.log(value);
      });
      // 输出的结果为:
      // Promise
      // done
      

      上述代码中,timeout返回一个Promise实例,表示过一段时间以后才会发生的结果。
      过了指定的时间(ms)后,Promise的状态变为resolved,然后触发.then的方法绑定的回调函数

      let promise = new Promise((resolve,reject) => {
          console.log('promise')
          resolve()
      })
      promise.then(() => {
          console.log('resolved')
      })
      console.log('Hi')
      // 输出结果:
      // ‘promise’
      // ‘Hi’
      // ‘resolved’
      

      这个例子中初始化后的Promise对象会立即执行,所以会先输出Promise,然后then方法制定的
      回调函数将在当前脚本中所有同步函数执行完后再去执行。所以,resolved最后输出

      let promise = new Promise(resolve => {
          console.log('promise')
          resolve()
      }).then(value => console.log('成功'))
      console.log('here')
      // 输出结果:
      // 'promise'
      // 'here'
      // 成功
      

      promise创建的过程是在js的同步任务中,所以会先输出promise,然后将resolve()放在微任务里。然后JS会继续执行剩下的同步任务,
      所以接下来会输出‘here’,最后当同步的任务执行完之后,开始执行微任务中的函数,输出‘成功’

      setTimeout(()=>{
          console.log('setTimeout')
      },0)
      let promise = new Promise(resolve => {
          console.log('promise')
          resolve()
      }).then(value => console.log('成功'))
      console.log('bottom')
      // 输出结果
      // promise
      // bottom
      // 成功
      // setTimeout
      

      代码执行中遇到setTimeout,会将setTimeout放到宏任务中,然后继续执行JS同步任务中的函数,首先是Promise的初始化,输出promise,
      然后遇到resolve后,会将resolve中的函数放在微任务中,继续执行同步任务中未执行的。输出bottom后,再输出成功,微任务执行完成后,会开始执行
      宏任务,输出setTimeout

      let promise = new Promise(resolve => {
         setTimeout(() => {
             console.log('setTimeout')
             resolve()
         },0)
         console.log('promise')
      }).then(value => console.log('成功'))
      console.log('bottom')
      // 输出结果
      // promise
      // bottom
      // setTimeout
      // 成功
      

      这个例子中首先JS会定义Promise,然后开始执行,发现setTimeout会将setTimeout放在宏任务中,然后继续执行,
      输出promise,此时还有同步任务没有执行完,所以会继续执行console.log('bottom'),输出bottom,执行完
      这步之后,JS同步任务已经执行完成了,接下来开始执行刚才放在宏任务中的setTimeout,先输出‘setTimeout’后,
      发现resolve,将其放在微任务中,如果此时setTimeout中还有其他的代码,会先执行setTimeout中的其他代码,
      再执行微任务中,输出‘成功’

    2. Promise.prototype.then()

      .then方法是定义在原型对象Promise.prototype上的。它的作用是为Promise添加回调函数。
      第一个参数是resolve状态的回调函数,第二个参数是reject状态下的回调函数then返回一个新的Promise实例,后面的then是对前面Promise的处理

      new Promise((resolve,reject) => {
          resolve('买水去了')
      }).then(
          value => {
              console.log(value)
          },
          error => {
              console.log(error)
          }
      )
      
    3. Promise.prototype.catch()

    Promise.prototype.catch()的方法是.then(null,rejection) 或 .then(undefined,rejection)的别名,用于指定发生错误时的回调函数。

        new Promise((resolve,reject) => {
            reject(new Error('出现错误'))
        }).then(value => {
            console.log(value)
        }).catch(err) => {
            console.log(err) // 出现错误
        }
    
        const promise = new Promise((resolve,reject) => {
            resolve('ok')
            throw new Error('test Error')
        })
        promise.then(value => {console.log(value)})
            .catch(error => {console.log(error)}) 
    
        // 输出结果
        //ok
    

    如果 Promise 状态已经变成resolved,再抛出错误是无效的。
    Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。

    1. Promise.prototype.finally()

    finally()方法用于不管Promise对象最后的状态如何,都会执行该操作

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

    finally方法的回调函数不接受任何参数,这就说明没办法知道前面的Promise的状态是fulfilled还是
    rejected.这就表明,在finally中的操作不依赖Promise的执行结果

    1. Promise.all()

    Promise.all()方法用于多个Promise实例,包装成一个新的promise实例

    const p = Promise.all([p1,p2,p3])
    p.then((res) => {
        // res是一个数组,是p1,p2,p3的返回值数组
    }).catch((err) => {
    
    })
    
    const p1 = new Promise((resolve, reject) => {
      resolve('hello');
    })
    .then(result => result)
    .catch(e => e);
    
    const p2 = new Promise((resolve, reject) => {
      throw new Error('报错了');
    })
    .then(result => result)
    .catch(e => e);
    
    Promise.all([p1, p2])
    .then(result => console.log(result))
    .catch(e => console.log(e));
    

    输出结果

    上述代码中p1会resolved,p2首先会rejected,但是p2有自己的catch方法,该方法返回一个新的Promise
    实例,p2的方法实际上指向这个实例。这个实例执行完catch的方法后,会变成resolveed,导致Promise
    方法参数里的两个实例都会resolved,因此会调用then中的方法

    如果p2中没有catch的方法,就会调用Promise.all()中的catch方法

    1. Promise.race() 和Promise.all()方法一样,这里不再赘述

    2. Promise.allSettled() -- ES2020

    Promise.allSettled()方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果,不管是fulfilled还是rejected,包装实例才会结束。该方法由 ES2020 引入。

    const p = [
        fetch('/api-1),
        fetch('/api-2),
        fetch('/api-3)
    ]
    await Promise.allSettled(p)
    removeLoadingIndicator()
    
    

    上面代码对服务器发出三个请求,等到三个请求都结束,不管请求成功还是失败,加载的滚动图标就会消失。

    该方法返回的新的 Promise 实例,一旦结束,状态总是fulfilled,不会变成rejected。
    状态变成fulfilled后,Promise 的监听函数接收到的参数是一个数组,
    每个成员对应一个传入Promise.allSettled()的 Promise 实例。

    当我们只关心异步操作有没有结束的时候,就可以用Promise.allSettled()的方法。Promise.all()无法确定所有请求都结束。

    1. Promise.any()
      ES2021 引入了Promise.any()方法。该方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回。
      只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;
      如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。

    Promise.any()跟Promise.race()方法很像,只有一点不同,
    就是不会因为某个 Promise 变成rejected状态而结束

  • 相关阅读:
    计算一个未排序数组中排序后相邻元素的最大差值
    13 类对象的声明中加小括号{}和不加小括号{}的区别
    12 表中删除重复项
    11 常量区的内容不能被修改
    10 无向图的边
    顺时针旋转矩阵
    字符串的旋转
    动态规划算法
    贪心算法应用-最小生成树
    贪心算法应用-单元最短路径
  • 原文地址:https://www.cnblogs.com/bllx/p/15927842.html
Copyright © 2020-2023  润新知