12-Promise

89 阅读3分钟

Promise

  • ES6新增的内置类,用来规划异步编程代码,解决回调地狱的 let p = new Promise([executor])
    • [executor]必须是一个函数,而且new Promise的时候会立即马上执行[同步操作]
    • p 是其创建的一个实例
      • 私有属性
      • [[PromiseState]]: "pending"/"flufiled"/"rejected" 实例的状态
      • [[PromiseResult]]: undefined 实例的值[成功的结果或失败的原因]
    • 公共方法:Promise.prototype
      • catch
      • then
      • finaly
    • p.then([onfulfiled],[onrejected])
      • [onfulfiled],[onrejected]都是函数

      • 实例状态是成功(fulfiled)时候,会把[onfulfiled]执行,并把实例的值作为成功的结果传递给他

      • 实例状态是成功(rejected)时候,会把[onrejected]执行,并把实例的值作为失败的原因传递给他

    • 如何修改实例的状态和值?
    • @1 基于这种创建实例 new Promise((resolve, reject) => {...})
      • resolve, reject都是函数 resolve("ok") -> 把实例p的状态修改为fulfiled,值(成功的结果)是"ok" reject("no") -> 把实例p的状态修改为rejected,值(失败的原因) 是 "no"
      • 如果 executor 执行报错,会把实例的状态修改为 rejected,值是报错原因
      • 一旦状态改变为fulfiled/rejected后面就不会改变状态值了
    • @2 每一次执行then方法,都会返回全新的Promise实例
      • let p2 = p.then([onfulfiled],[onrejected])
      • 不论[onfulfiled],[onrejected]是哪个函数执行(由p的状态来决定的),方法的执行决定p2的状态和值
      • 首先看方法是否报错,报错了,p2是失败态(rejected),值是报错原因
      • 不报错,再看返回值
        • 如果返回新的Promise实例 -> @np,则@np的状态和值决定p2的状态和值
        • 返回不是新实例,p2状态成功,值时函数的返回值
// => 例子1
let p = new Promise(() => {
  console.log("我是同步的");
  // resolve("ok"); //成功
  // reject("no"); //失败
  // throw new Error("我搞出来的失败")
  resolve(10);
})
let p2 = p.then(res => {
  console.log(res, "成功res");// 10
}, reason => {
  console.log(reason, "失败reason");
})
p2.then(res => {
  console.log(res, "成功res");// undefined
}, reason => {
  console.log(reason, "失败reason");
})
  • 执行Promise.resolve/reject/all/race等静态方法,也会创建新的Promise实例
    • Promise.resolve(10) 创建状态时成功fulfiled,值为10的实例
    • Promise.reject(0) 创建状态是失败rejected,值为0的实例

题目1

Promise.resolve(10)
  .then(val => {
    console.log("成功", val);// ①  => 10
    return Promise.reject(val / 10);// 1
  })
  .then(val => {
    console.log("成功", val);
    return val + 10;
  }, reason => {
    console.log("失败", reason);// ② => 1
    return reason - 10;// => -9
  })
  .then(val => {
    console.log("成功", val);
    return val + a;
  }, reason => {
    console.log("失败", reason);// ③
    return val - a;//报错
  })
  .then(val => {
    console.log("成功", val);
  },reason => {
    console.log("失败", reason);//④  ReferenceError: a is not defined
  })

image.png

  • then链的穿透/顺延机制
    • .then([onfulfiled],[onrejected]),2个方法可传可不传,不传则顺延到下一个then中,相同状态要执行的方法中处理
    • 我们不设置方法: Promise内部会默认加一个方法,可以实现状态的顺延和穿透
Promise.resolve(10)
  .then(null, reason => {
    console.log("失败", reason);
  })
  .then(val => {
    console.log("成功", val);// => 10
  },reason => {
    console.log("失败", reason);
  })
  
// => null是 onfulfiled 函数的时候 默认 val => return val
// => null 是 onrejected 函数的时候 默认 reason => throw reason

image.png

  • p.catch 等价与 p.then(null, onrejected)
  • .finally 不论成功还是失败,最后都会执行[一般不用]

Promise.all/any/race

let p = Promise.all([promises]);

  • promises是包含0到多个promise实例的集合,一般是数组,如果有一项不是promise实例,则默认是状态转为成功,值是本身的promise实例 只要有一例是失败的就是失败,值是本次失败的原因,后面的操作不再处理
let p1 = new Promise(resolve => {
  resolve(1);
})
let p2 = new Promise(resolve => {
  setTimeout(() => {
    resolve(2);
  }, 2000);
})
let p3 = 3;// 默认变成 Promise.resolve(3)

Promise.all([p1, p2, p3])
  .then(res => {
    console.log(res);// 2秒后得到 [ 1, 2, 3 ]
  })

Promise.any: 只要有一个成功就是成功,值是本次成功的结果;都失败,最后p才是失败([Promise.any]方法在node.js 15.0.0中受支持)

Promise.race: 集合谁最先得到结果的就以谁的为主,不管成功or失败

项目中的一些用法

  • 第一个成功才会调第二个实例
axios.get('/api1')
    .then(val => {
        return axios.get('/api2');
    })
    .then(val => {
        console.log(val);
    })
  • 睡眠函数
const sleep = (interval = 1000) => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve();
        }, interval);
    })
}

sleep().then(() => {
    //...处理内容
})