Promise

Overview
Promise 是 JavaScript 语言的核心特性,适用于所有支持 ES6 或更高版本的 JavaScript 环境,包括浏览器和 Node.js
异步编程模型:Promise 提供了一种更清晰、更可控的方式来处理异步操作的结果,相比传统的回调函数 callback,它可以更好地避免回调地狱问题
函数类型,实际上是一个对象
承诺在未来某个时刻可能完成并返回结果:成功或失败
更多信息,请查看 8个Promise高级技巧,让你在前端开发中如虎添翼!
console.log(typeof (Promise)); //function
//或
console.dir(Promise);
Lifetime
待定状态 pending;还没有完成;未执行;状态不确定
履行状态 fulfilled;完成且执行成功
拒绝状态 rejected;完成且执行失败;被拒绝

.访问错误

.网络链接失败、请求超时

.服务器返回 404 错误或非 2xx 或 3xx 状态码

.promise链中任何一个抛出的错误

then()
.所有Promise对象都有的方法
.使用两个参数处理结果,包括:成功和失败;第一个参数处理成功,第二个参数处理失败或异常
1.履行处理器 fulfillment handle - 使用 resolve() 函数表示 Promise 处理成功,给出结果
2.拒绝处理器 rejection handle - 使用 reject() 函数表示 Promise 处理失败,给出结果
.都是可选的;可以选择性的监听履行、拒绝或全部
.全部监听
let promise = fetch(url)

promise.then(resolve => {
    //fulfillment handle
}, reject => {
    //rejection handle
})  
.只监听成功
let promise = fetch(url)

promise.then(resolve => {
//fulfillment handle
})  
.只监听拒绝
let promise = fetch(url)

promise.then(null, reject => {
    //rejection handle
})  
catch()
.使用 catch() 分配 拒绝处理器 - 处理失败/捕获异常,专门处理失败的情况;相当于上面只监听拒绝的情况
常见异常捕获类型
分类 说明
运行时错误 程序执行过程中发生的错误,例如除以零、数组越界、空指针引用等
自定义异常 自定义异常来表示特定的错误条件或业务规则违反
系统异常 操作系统或编程语言环境可能会抛出一些系统级别的异常,比如文件未找到、权限不足等
库或框架异常 使用第三方库或框架时,如果调用的方法内部出现错误,这些库或框架可能会抛出异常
类型异常 在强类型语言中,类型不匹配或其他类型相关的错误也可能导致异常
逻辑错误 逻辑错误通常不会立即导致程序崩溃;某些情况下,可以选择通过抛出异常的方式来中断程序流程,便于调试和处理
let promise = fetch(url)

promise.catch(reject => {
    //rejection handle
})  
.除了处理拒绝处理器,还可以捕获履行处理器抛出的异常;这样仅仅使用一个拒绝处理器,就可以处理所有的失败或异常
.当在 Promise 链上使用 catch 方法时,它会捕获前面的 Promise 链中任何未处理的 rejected 错误:可以不在 then() 中处理,而在 catch() 中处理
.注意:履行状态和拒绝状态一旦确定,就不可以更改;所以履行状态抛出的错误不能被拒绝状态捕获,只能由 catch 捕获
.因此,通常情况下,使用 then() 处理成功,使用 catch() 处理异常,更加符合 Promise 的语义和人们的思维习惯
let promise = fetch(url)

promise.then(resolve => {
  //fulfillment handle
})

promise.catch(reject => {
    //rejection handle
}) 
finally()
.使用 finally() 分配 解决处理器 - 表示处理结束,不管处理结果如何
.可以集中处理结束后的逻辑,而不用在成功和失败中分别处理;如进度条/加载指示器的处理,不管数据加载是否成功,最后都要隐藏进度条
.解决处理器无法使用返回,return 将被忽略;所以如果后续继续使用 Promise,则得不到结果
let promise = fetch(url)

promise.finally(log => {
  console.log('log', log);
})
Mehtods
all()
.以数组的形式监听多个 Promise
.返回结果数组,一一对应
.只有所有的结果都是履行状态,结果才是履行状态;如果有一个是拒绝状态,则结果为拒绝状态
.全部成功:只有当所有的 Promise 都 resolve(成功)时,返回的 Promise 实例才会 resolve,并将每个输入 Promise 的 resolve 值组成一个数组
.任意失败则整体失败:如果传入的任何一个 Promise 变为 rejected(失败),或者传入的不是一个 Promise,则 Promise.all() 立即 reject,并将第一个错误原因作为其结果
.处理相互独立的任务时能显著提高效率
[] 彼此无需依赖关系,如同时请求A、B、C,可以并行请求;如首页加载:轮播图、用户信息、商品列表、活动信息等诸多内容
let promises = Promise
  .all([f0(), f1(), f2()])
  .then(e => {
    console.log('all ok')
    console.dir(e)
  })
  .catch(err => {
    console.log('err', err)
  })
  .finally(() => {
    console.log('all done')
  })

function f0() {
  return fetch('/utils/data/cart.json')
    .then(res => res.json())
}

function f1() {
  return fetch('/utils/data/form.json')
    .then(res => res.json())
}

function f2() {
  return fetch('/utils/data/coffee.json')
    .then(res => res.json())
}
any()
.监听多个 Promise;一旦有一个确定是履行,则返回履行状态;只有所有都被拒绝,返回才是拒绝状态
.任何一个被成功执行即可
race()
.监听多个 Promise;最后的状态取决于最快确定状态的哪个
.一旦有一个确定状态,则结束;如果是履行状态,则返回履行状态;如果是拒绝状态,则返回拒绝状态
then()、catch()、finally()、all() 等等都产生一个新的 Promise
链式
.有利于捕获前面履行处理器或拒绝处理器的产生的错误
.有利于数据从上一个 Promise 传递下一个 Promise
let promise = fetch(url)

promise.then(res => {
    // fulfillment handle
}).catch(err => {
    // rejection handle
}).finally(log => {
    // finally handle
})      
.彼此有制约关系,如先拿到A后才可以继续请求B,然后再请求C
pa()
.then(res => {  // 拿到的是pa的结果
  console.log(res);
  return pb()
})
.then(res => {  //拿到的是pb的结果
  console.log(res);
  return pc()
})
.then(res => {  //拿到的是pc的结果
  console.log(res);
})
Constructor
.构造函数接收一个 执行器 Executor 函数作为参数
.执行器执行成功,调用 resolve()
.执行器执行失败,调用 reject()
独立写法
let promise = new Promise((resolve, reject) => {
  resolve('fulfilled')
  reject('rejected')
})

promise.then(res => {
  console.log(res);
}, err => {
  console.log(err);
})

promise.catch(err => {
  console.log(err);
})

promise.finally(log => {
  console.log('ending for log');
})
链式写法
let promise = new Promise((resolve, reject) => {
  resolve('fulfilled')
  reject('rejected')
})
  .then(res => {
    console.log(res);
  }, err => {
    console.log(err);
  })
  .catch(err => {
    console.log(err);
  })
  .finally(log => {
    console.log('ending for log');
})
状态
pending

待处理 - 调用Promise时,初始状态为 pending,表示还没有开始

let promise = new Promise((resolve, reject) => {
})

console.log(promise);
fulfilled

执行成功时,调用resolve,将Promise的状态改为fulfilled

let promise = new Promise((resolve, reject) => {
  resolve('fulfilled')
})

console.log(promise);

promise.then(res => {
  console.log(res);
})
rejected

Promise 执行过程中遇到错误或者无法完成预期操作时,Promise的状态改为rejected

let promise = new Promise((resolve, reject) => {
  reject('rejected')
})

console.log(promise);

promise.catch(err => {
  console.log(err);
})
let flag = false
let promise = new Promise((resolve, reject) => {
  flag ? resolve('data: fulfilled') : reject('data rejected');
})
  .then(res => {
    console.log(res);
  }, err => {
    console.log('then err', err); //拒绝后,如果这里处理过了,catch()就不再处理
  })
  .catch(err => {
    console.log('catch err', err);  //如果then()中没有处理异常,这里就必须处理
  })
  .finally(log => {
    console.log('ending for log');
  })