Promise:JS中进行异步编程的解决方案

Promise的基础概念

Promise在js当中,是异步编程的一种解决方案。Promise对象封装一个异步操作并获取其成功失败的返回值,通过resolve/reject这两个方法来处理成功与失败(例如:网络请求,定时器,数据库操作等)。

示例:

js 复制代码
let p = new Promise((resolve, reject) => {
        resolve("你好,promise")
      })
      p.then(
        (value) => {
          console.log(value, "===value===")
        },

        (error) => {
          console.log(error, "===error===")
        }
      )
//结果打印:你好,promise

为什么要使用Promise呢?

在开发当中我们接触的异步编程不在少数,而我们常见的网络请求和定时器都离不来异步操作,早期一般会通过回调函数来解决这类问题,但是我们常常会遇到几个网络请求相互联系,如果使用回调函数一步步的回调操作,很容易就会产生回调地狱问题,一旦业务过于复杂或者长期迭代,代码就会十分用臃肿,难以维护。正是Promise的横空出世才解决地狱回调的问题。

Promise的状态属性

Promise有三种状态,分别是pending,fulfilled,rejected。下面我们一一了解。

pending:进行中,等待的状态

在没有遇到(resolve,reject)之前,Promise将一直处于pending状态。其状态只能改变一次,一般来说只能由进行中变成成功/失败(pending-->fulfilled/rejected),不能由成功变成失败,或者失败变成成功,如果看见状态一直处于pending时,说明Promise对象当前的状态并没有被是Promise的执行器函数resolve/reject改变。

js 复制代码
  let p = new Promise((resolve, reject) => {})
      console.log(p, "===p===")

fulfilled:成功状态

Promise对象通过resolve将Promise的状态由pending改变成fulfilled。

js 复制代码
      let p = new Promise((resolve, reject) => {
        resolve("wow!")
      })
      console.log(p, "===p===")

rejected:失败状态

Promise对象通过reject将Promise的状态由pending改变成rejected。

js 复制代码
      let p = new Promise((resolve, reject) => {
        reject("wuwuwu!")
      })
      console.log(p, "===p===")

Promise的工作流程

首先通过new创建一个新的Promise对象,此时Promise的状态是处于pending状态。然后执行异步操作,执行resolve或者reject方法,将pending状态变成成功或者失败(fulfilled/rejected)的状态。如果我们执行resolve()将状态从pending变成fulfilled时,调用Promise实例上的then方法,执行then方法中第一个参数(成功的回调函数)的方法,最后抛出一个新的Promise对象;相反,如果我们执行reject()将状态从pending变成rejected时,我们可以通过Promise实例上的then方法(失败的的回调函数)或者catch方法返回一个新的Promise对象。

Promise的方法

1.Promise.resolve()

Promise.resolve() 静态方法接收一个值,返回一个成功或者失败的Promise对象,它的作用就是快速得到一个Promise对象。Promise.resolve() 实际上相当于 new Promise((resolve) => resolve(value))的简写。传入的值如果为一个非Promise的值,会返回成功的状态,传入的值如果是Promise对象,则返回值的状态要根据传入的Promise对象的状态来决定。

js 复制代码
      let p = Promise.resolve("ok")
      let p1 = Promise.resolve(
        new Promise((resolve, reject) => {
          resolve("成功了")
        })
      )
      let p2 = Promise.resolve(
        new Promise((resolve, reject) => {
          reject("失败了")
        })
      )
      console.log(p, "=====非Promise====")
      console.log(p1, "=====resolve====")
      console.log(p2, "=====reject====")
    //爆红是因为失败了,用catch接收一下就可以了

2.Promise.reject()

Promise.reject()静态返回一个失败的Promise对象,不管传入的值是非Promise对象还是Promise对象,返回的一直都是失败的Promise对象。

js 复制代码
      let p = Promise.reject("非Promise对象")
      let p1 = Promise.reject(
        new Promise((resolve, reject) => {
          resolve("失败了吗")
        })
      )
      let p2 = Promise.reject(
        new Promise((resolve, reject) => {
          reject("失败了吗")
        })
      )
      console.log(p, p1, p2)

3.Promise.all()

Promise.all()静态方法的参数一般为Promise组成的一个数组,并且传入数组的的Promise都为成功的状态时才能成功的返回一个成功的Promise对象。如果传入数组中有一个失败,返回的结果就是我们传入数组中失败的Promise的结果。

js 复制代码
let p1 = Promise.resolve("1")
      let p2 = Promise.reject("2")
      let p3 = Promise.resolve(
        new Promise((resolve, reject) => {
          resolve("3")
        })
      )
      let p4 = Promise.resolve(Promise.resolve("4"))
      let result1 = Promise.all([p1, p2, p3])
      let result2 = Promise.all([p1, p3, p4])
      console.log(result1, result2)

4.Promise.race()

Promise.race()方法的参数一般也是Promise组成的一个数组,最终返回一个新的Promise对象。与Promise.all()不同的是,它是根据传入数组的第一个Promise对象的结果状态来改变。

js 复制代码
      let p1 = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve("ok")
        }, 1000)
      })
      let p2 = Promise.reject("2")
      let p3 = Promise.resolve(
        new Promise((resolve, reject) => {
          resolve("3")
        })
      )
      let result1 = Promise.race([p1, p2, p3])
      let result2 = Promise.race([p3, p2, p1])
      console.log(result1, result2)

Async/Await

async/await也是一套关于异步的解决方案,是基于Promise的二次封装的语法糖。两者相比较而言,async/await更加的简洁明了。两者区别在于Promise返回的结果通常需要用then来接收返回值,而async/await直接在函数体内就可以处理结果。深层次的使用Promise可能也会导致回调地狱,而async/await提供了类似同步代码结构,更易维护。两者相比async/await更加优雅,注意一点await只能用在async标记的函数内使用。

js 复制代码
const handleCallBack = () => {
        return new Promise((resolve, reject) => {
          if (Math.floor(Math.random() * 10 + 1) > 5) {
            resolve("我大于5")
          } else {
            reject("我小于等于5")
          }
        })
      }
      //Promise
      handleCallBack()
        .then((value) => {
          console.log(value, "====Promise方式==成功==")
        })
        .catch((error) => {
          console.log(error, "====Promise方式==失败==")
        })

      // async/await
      async function handleAsync() {
        try {
          let data = await handleCallBack()
          console.log(data, "====async/await方式==成功==")
        } catch (error) {
          console.log(error, "====async/await方式==失败==")
        }
      }
      handleAsync()
相关推荐
雯0609~15 分钟前
网页F12:缓存的使用(设值、取值、删除)
前端·缓存
℘团子এ18 分钟前
vue3中如何上传文件到腾讯云的桶(cosbrowser)
前端·javascript·腾讯云
学习前端的小z24 分钟前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
彭世瑜1 小时前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund4041 小时前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
Backstroke fish1 小时前
Token刷新机制
前端·javascript·vue.js·typescript·vue
小五Five1 小时前
TypeScript项目中Axios的封装
开发语言·前端·javascript
小曲程序1 小时前
vue3 封装request请求
java·前端·typescript·vue
临枫5411 小时前
Nuxt3封装网络请求 useFetch & $fetch
前端·javascript·vue.js·typescript
前端每日三省1 小时前
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
开发语言·前端·javascript