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()
相关推荐
腾讯TNTWeb前端团队4 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰8 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪8 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪8 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy9 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom9 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom9 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom9 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom10 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom10 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试