这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战
Promise
01. 是什么
-
Promise是:
-
是异步编程的一种解决方法
-
从语法上讲:Promise是一个对象,可以获取异步操作的消息
-
从本意上讲:Promise表示承诺,它承诺过一段事件会给你一个结果
-
Promise创建后会立即执行
-
02. 为什么
- Promise对象可以:
- 表示一个异步操作的最终完成(或者失败)及其结果值
- 可以解决回调地狱的缺陷
03. 三种状态
-
初始化状态:pending,表示操作进行中
-
已兑现状态:fulfilled,表示操作成功
-
已拒绝状态:rejected,表示操作失败
Promise在创建时,状态为pending,状态一经改变就无法再改变
且,状态改变只有两种情况:
pending => fulfilled、pending => rejected状态改变后,就称为
resolved,表示状态已决定了
04. 结构
-
Promise是一个构造函数,需要结合new使用let promise = new Promise() -
Promise接收一个函数作为参数,这个函数包含两个参数resolve和rejectresolve:异步操作成功时调用,并会将成功结果作为参数传递出去- 其作用就是将
Promise的状态从pending改变为resolved
- 其作用就是将
reject:异步操作失败时调用,并将失败的错误作为参数传递出去- 其作用就是将
Promise的状态从pending改变为rejected
- 其作用就是将
let promise = new Promise(function(resolve, reject){ resolve(success) // reject(error) }) -
即使异步操作已经完成(成功或失败),在这之后通过
.then()添加的回调函数也会被调用- 通过多次调用
.then()可以添加多个回调函数,它们会按照插入顺序进行执行
- 通过多次调用
05. 返回值的处理
-
Promise中的任意返回值都会被包裹为
promise对象,然后但不能返回Promise本身,否则死循环
-
.then()方法可以接受两个回调函数作为参数- 第一个回调函数是异步操作成功时调用
- 第二个回调函数是异步操作失败时调用,非必填
promise.then( function(success){ // do something }, function(error){ // do something } ) -
.then()会在操作成功时执行,.catch()会在操作失败时执行.catch()方法可以看作是.then(null,failureCallback)的缩略形式
promise .then(()=>{ // success }) .catch(()=>{ // error }) -
.finally方法在Promise结束的时候,无论结果为resolved还是rejected,都会执行里面的回调函数- 回调函数不需要传入参数
- 其返回值也是一个
Promise,是上一次的Promise对象的值- 如果是异常,则返回异常的Promise对象
Promise可以进行链式调用、多次调用
- 链式调用:
Promise.then().catch()- 多次调用:
Promise.then()、Promise.then()
但Promise的构造函数只会执行一次,且状态已经改变就不再变化
因此,后续每次调用
.then()或者.catch()都会直接拿到构造函数返回值
06. 关于返回错误:
-
在
.then()中- 可以通过
throw new Error()抛出错误 - 可以通过
return Promise.reject(new Error('错误信息'))返回错误
- 可以通过
-
接收错误
- 通过
throw抛出的错误,可以在.catch()中接收这个错误 - 通过
return返回错误,则会被包裹为Promise对象,无法被.catch()捕获
- 通过
-
在链式调用中,
.catch()不管被链接到哪里,都可以捕获到上层未捕捉的错误
07. 值透传
-
.then或者.catch的参数期望是函数,传入非函数则会发生值透传Promise.resolve(1) .then(2) .then(Promise.resolve(3)) .then(console.log) // 输出结果: 1第一个
then和第二个then中传入的都不是函数- 一个是数字类型,一个是对象类型
- 因此发生了透传,将
resolve(1)的值直接传到了最后一个then里
08. 同步、异步
-
Promise新建后立即执行,即Promise构造函数里的代码同步执行的
-
而当Promise状态结束的时候,就会立即**放进异步队列中
.then()函数是异步的,需要在JS事件队列所有运行时间结束了,且事件队列被清空之后,才开始执行.then()需要在回调函数resolve之后,才会执行里面的内容
09. async/await
-
关于
async / awaitasync function foo() { // await 前面的代码 await bar(); // await 后面的代码 } -
分析:
-
await前面的代码 是同步执行的,- 它相当于函数
foo内部的同步代码 - 调用函数时会直接执行(当然要遵循事件循环机制)
- 它相当于函数
-
await所在行的代码会从右往左执行,或者说,await后面的函数会先执行一遍- 它相当于
Promise()构造函数内的代码- 注:是构造函数内,而不是回调函数
- 所以它也是同步执行的
await表示等待右侧表达式完成
- 它相当于
-
await后面的代码则会被放到 Promise 的.then()方法里 -
所以
async/await可以转换为:function foo() { // await 前面的代码 Promise(resolve => { bar() resolve() }).then(() => { // await 后面的代码 }); }
-
-
错误处理
- 如果
await所在行的代码,后面返回的结果是一个状态为rejected的Promise对象- 那么,代码执行到这里就会返回结果,并且不会再继续向下执行
- 为了避免这个问题
- 可以在后面直接跟上
.catch() - 可以使用
try catch
- 可以在后面直接跟上
- 如果
10. .all()和.race()
-
Promise.all()接收一个Promise 对象数组作为参数- 它可以并行执行多个异步操作
- 并且在所有异步操作执行完成后,才执行回调
- 且只有全部为
resolve时,才会在.then()里接收 - 可以在
.then()回调里接收所有的异步处理结果,结果顺序和数组顺序一致
-
Promise.race()接收一个Promise 对象数组作为参数- 它可以并行执行多个异步操作
- 且,只会保留取第一个执行完成的异步操作的结果
- 其它方法仍然会执行,不过执行结果会被抛弃
本人前端小菜鸡,如有不对请谅解