ES6 中的 Promise

1、什么是Promise

  • Promise 是一个类
  • 当通过 new Promise() 创建时,需传入一个执行函数 ,我们称之为 executer
    • executer 在 Promise 创建时会立即执行,并传入两个回调函数作为参数:executer(resolve, reject)
    • 当调用 resolve 回调函数时,会执行 Promise 对象的 then 方法传入的回调
    • 当调用 reject 回调函数时,会执行 Promise 对象的 catch 方法传入的回调
  • Promise 是一个状态机,分为 3种状态 :
    • pending :待定状态,执行 executer 后,处于该状态。(初始状态)
    • fuifilled :兑现状态,调用 resolve 后,Promise 状态变更为 fulfilled,且无法再次更改。
    • rejected :拒绝状态,调用 reject 后,Promise 状态变更为 rejected,且无法再次更改。
javascript 复制代码
// 模拟网络请求
function request(cb) {
    let flag = !!(Math.random() <= 0.5)
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (flag) {
                resolve("成功消息")
                return;
            } 
            reject("失败消息")
        }, 1000)
    })
}

console.log("请求开始")

request().then(
    msg => {
        console.log("成功",msg)
    },
    err => {
        console.log("失败",err)
    }
)

2、resolve 的参数

  • 如果传入的是普通的值或者推向,则会传递到 then 方法的参数中
  • 如果传入的是一个 Promise ,则当前 Promise 状态会由传入的Promise决定
javascript 复制代码
const prom = new Promise((resolve, reject) => {
    resolve('success')
})

new Promise((resolve, reject) => {
    resolve(prom)
}).then(data => {
    console.log("data", data)
}).catch(err => {
    console.err("err", err)
})

// 输出 data success
  • 如果传入的是一个 thenable对象 ,会执行对象的 then 方法,由该 then 方法决定后续状态
javascript 复制代码
new Promise((resolve, reject) => {
    resolve({
        then(resolve,reject) {
            reject("error)
        }
    })
}).then(data => {
    console.log("res", res)
}).catch(err => {
    console.log("err", err)
})

// 输出 err error

3、Promise 的实例方法

then 方法

  • 概念

    • 通过 then 方法可以对 Promise 中的 resolve 进行处理,then 方法的返回值是一个新的 Promise 实例
  • 多次调用 then 方法

    • 同一个 Promise 实例可以同时调用多个 then 方法,当 Promise 中的 resolve 被调用时,所有的 then 方法传入的回调函数都会被调用

      javascript 复制代码
      const prom = new. Promise(resolve => {
          resolve("你好")
      })
      
      prom.then(msg => console.log(msg))
      prom.then(msg => console.log(msg))
      prom.then(msg => console.log(msg))
      
      /* 输出
      你好
      你好
      你好
      */
  • then 方法传入的回调函数可以有返回值

    • 如果返回的是普通值 ,那么这个普通值作为一个新的 Promise 的 resolve 值

      javascript 复制代码
      const prom = new Promise(resolve => {
          resolve("你好");
      })
      
      prom.then(() => 'then').then(res => console.log(res))
      
      // prom.then(() => 'then')等价于
      prom.then(() => {
          return new Promise(resolve => {
              resolve('then')
          })
      })
      
      // 输出 then
    • 如果返回的是 Promise ,那么就可以再次调用此 Promise 的 then 方法

    • 如果返回的是一个 thenable 对象 ,则 resolve 会传递给下一个 Promise

      javascript 复制代码
      const promise = new Promise(resolve => {
        resolve('你好')
      })
      
      promise.then(() => {
        return {
          then(resolve) {
            return resolve('success')
          }
        }
      }).then(msg => console.log(msg))
      
      // 输出 success

catch 方法

除了 then 方法的第二个参数来捕获 reject 错误外,我们还可以通过 catch 方法来捕获,catch 返回的也是一个新的 Promise。

javascript 复制代码
const promise = new Promise((resolve, reject) => {
  reject('error') 
})

promise.then(undefined, err => {
  // 打印err
  console.log(err)
})
// 这种写法不太符合'promise/a+规范'
promise.catch(err => {
  // 打印err
  console.log(err)
})
// 符合规范的写法
promise.then(() => {}).catch(err => {console.log(err)})

*注意* catch 本质上是对 Promise 的 then 方法的封装,所以同样也是可以多次调用 的,只要保证 Promise 实例的状态是 rejected ,那么就会调用 catch 方法

finally 方法

Promise 实例 状态无论是变更为 fulfilled 还是 rejected,finally 方法都会执行,finally 方法不接受任何的参数

javascript 复制代码
const promise = new Promise((resolve, reject) => {
  reject('error') 
})

promise.then(() => {}).catch(err => {console.log(err)}).finally(() => {
  console.log('finally code execute')
})

4、Promise 的类方法

resolve 方法

  • 参数
    • 参数本身是 Promise
    • 参数是 原始值/普通对象
    • 参数是一个 thenable对象
javascript 复制代码
const foo = {
    name: "alex"
}

function bar(obj) {
    return new Promise(resolve => {
        resolve(obj)
    })
}

bar(foo).then(res => {
    console.log(res)
})

// 其中的 function bar 等价于

function bar1(obj) {
    return Promise.resolve(obj)
}

reject 方法

Promise.reject() 方法和 Promise.resolve() 方法 用法类似,主要区别是,reject方法用于处理Promise 拒绝逻辑

all 方法

Promise.all(proms) ,参数接收一个 Promise 队列,返回的是一个 Promise 实例,当 proms 总的所有 Promise 执行完成 且 状态均为 fulfilled 时,结果实例的状态才会变为 fulfilled,反之,结果实例的状态为 rejected。

当 Promise.all(proms) 的状态为 fulfilled 时,then(res) 的参数 res 就是 proms 对应实例成功后的值所形成的数组。

javascript 复制代码
let i = 0;
function genPromise() {
    return Promise.resolve(`success${i = i + 1}`)
}

const proms = [
    genPromise(),
    genPromise(),
    genPromise(),
];

Promise.all(proms).then(res => {
    console.log('res' , res)
})

// 输出 ['success1', 'success2', 'success3']

当 Promise.all(proms) 的参数 proms 中存在 rejected 时,结果实例状态也会更改为 rejoiced,同时返回停止运行剩余 Promise ,结果返回 状态为 rejected 的 Promise 的值。

javascript 复制代码
let i = 0;
function genPromise() {
  return new Promise(resolve => {
    resolve(`success${(i = i + 1)}`)
  })
}
const promiseArr = [
  genPromise(),
  new Promise((resolve, reject) => {
    reject('error1')
  }),
   new Promise((resolve, reject) => {
    reject('error2')
  })
]
Promise.all(promiseArr).then(res => {
  console.log('res', res)
}).catch(err => {
  console.log(err)
})

// 输出 'error1'

allSettled 方法

  • 参数接收一个 Promise 队列,返回 一个Promise 实例
  • 返回 Promise 实例,会在所有 Promise 实例执行完毕后,状态方可变更为 fulfilled,且结果实例状态只能由 pending ------> fulfilled.
  • 无论队列中的 Promise 实例的状态如何,都能获取到结果
javascript 复制代码
const promiseArr = [
  new Promise((resolve, reject) => {
    resolve('success1')
  }),
  new Promise((resolve, reject) => {
    reject('error')
  }),
  new Promise((resolve, reject) => {
    resolve('success2')
  }),
]

Promise.allSettled(promiseArr).then(res => {
  console.log('res', res)
})

/* 结果:
    res [
      { status: 'fulfilled', value: 'success1' },
      { status: 'rejected', reason: 'error' },
      { status: 'fulfilled', value: 'success2' }
    ]
*/

race 方法

  • 参数接收一个 Promise 队列,返回一个 Promise 实例
  • 对 Promise 队列的完成情况进行监控,当某个任务最前完成(无论是fulfilled/rejected),那么返回的结果实例状态也会对应的变更,同时捕获最先完成的 Promise 的结果
javascript 复制代码
const promiseArr = [
   new Promise((resolve, reject) => {
    setTimeout(() => {
       resolve('success1')
    }, 1000)
  }),
  new Promise((resolve, reject) => {
    setTimeout(() => {
          reject('error')
    }, 2000)
  }),
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('success2')
    }, 3000)
  }),
]

Promise.race(promiseArr).then(res => {
  console.log('res', res)
}).catch(err => {
  console.log('err', err)
})

// 结果 res success1

any 方法

  • 参数接收一个 Promise 队列,返回一个 Promise 结果实例
  • 当某个 Promise 状态变更为 fulfilled 或 所有的 Promise 状态均为 rejected 时,结果实例的状态才能确定并返回
javascript 复制代码
const promiseArr = [
   new Promise((resolve, reject) => {
    setTimeout(() => {
       reject('error')
    }, 2200)
  }),
  new Promise((resolve, reject) => {
    setTimeout(() => {
          reject('error')
    }, 2000)
  }),
  new Promise((resolve, reject) => {
    setTimeout(() => {
      reject('error')
    }, 3000)
  }),
]

Promise.any(promiseArr).then(res => {
  console.log('res', res)
}).catch(err => {
  console.log('err', err)
})
// 遇到第一个fullfilled,那么转变返回的Promise实例的状态
// 如果所有的都是rejected, 那么只有所有执行完毕后,返回的Promise实例才会转变
// 并且会抛出错误
相关推荐
去伪存真12 分钟前
构建你的第一个 DevOps AI Agent:自动化捕获、分析并修复 CI 故障
前端·agent
niucloud-admin23 分钟前
JAVA V6 多商户商城 开发文档——手机端前端
java·开发语言·前端
喵个咪26 分钟前
GoWind Admin|风行 — 开箱即用的企业级全栈中后台框架:脚本系统实战
javascript·后端·go
樱花落木兰29 分钟前
SpringBoot + ECharts 后台数据统计报表模块实战
java·javascript·spring boot·ai·log4j·github·echarts
skywalk816333 分钟前
deepseekharness在对话中,有四种模式,分别是极简、PTC、创造和标准模式,每种模式下挂载的插件、skill等数量不一样
前端·人工智能·实践
愛芳芳41 分钟前
element-plus+vite+vue3+pinpa+mock+typeScript搭建经典的电商管理后台
前端·javascript·typescript
liangshanbo12151 小时前
面试题:常见的前端构建工具有哪些?分别适用于什么场景?
前端
事圆则缓1 小时前
Flutter 状态管理框架对比(三):Riverpod 如何连起购物车与异步价格
开发语言·javascript·flutter
linux_cfan1 小时前
videojs v10 源代码系列解读:30 · `SerialRunner` 与 `ConcurrentRunner`
前端
liangshanbo12151 小时前
面试题:页面需要发起大量 Ajax / HTTP 请求时,如何优化请求性能?
前端·http·ajax