js【详解】Promise(含 Promise 的三种状态及其变化,创建 Promise, Promise.all 语法、Promise.all 实战范例、手写 Promise.all)

简介: js【详解】Promise(含 Promise 的三种状态及其变化,创建 Promise, Promise.all 语法、Promise.all 实战范例、手写 Promise.all)

为什么需要使用 Promise ?

传统回调函数的代码层层嵌套,形成回调地狱,难以阅读和维护,为了解决回调地狱的问题,更加优雅地书写复杂的异步任务,诞生了 Promise

什么是 Promise ?

Promise 是一种异步编程的解决方案,本身是一个构造函数

console.log(Promise); // [Function: Promise]

自带resolve,reject,all 等方法,其原型上还有then、catch等方法。

Promise 的三种状态及其变化

  1. pending 进行中,不会触发 then 和 catch 回调函数
  2. resolved / fulfilled 已成功,会触发后续的 then 回调函数
  3. rejected 已失败,会触发后续的 catch 回调函数


Promise 的状态变化如上图所示,不可逆

  • Promise 最初的状态是 pending
  • pending 状态的 Promise 执行 resolve() 后,状态变为 resolved
Promise.resolve(); // Promise 的状态从 pending 变为 resolved

resolved 状态的 Promise 会触发后续的 then 函数,

  • 若 then 函数内没有报错,则返回一个 resolved 状态的 Promise
Promise.resolve().then(() => {}); // 最终 Promise 的状态为 resolved

若 then 函数内报错,则返回一个 rejected 状态的 Promise

Promise.resolve().then(() => {
  throw new Error("then函数出现报错");
}); // 最终 Promise 的状态为 rejected

pending 状态的 Promise 执行 reject() 后,状态变为 rejected

Promise.reject(); // Promise 的状态从 pending 变为 rejected

rejected 状态的 Promise 会触发后续的 catch 函数,

  • 若 catch 函数内没有报错,则返回一个 resolved 状态的 Promise
Promise.reject().catch(() => {}); // 最终 Promise 的状态为 resolved

若 catch 函数内报错,则返回一个 rejected 状态的 Promise

Promise.reject().catch(() => {
  throw new Error("catch函数出现报错");
}); // 最终 Promise 的状态为 rejected

创建 Promise

新创建的 Promise 实例的状态为 pending

// 此时,p1 的状态为 pending
const p1 = new Promise((resolve, reject)=>{
 
})

执行 resolve() ,Promise 实例的状态变为 fulfilled

const p1 = new Promise((resolve, reject) => {
  resolve()
})

执行 reject() ,Promise 实例的状态变为 reject

const p1 = new Promise((resolve, reject) => {
  reject()
})

Promise.all

Promise .all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.all([p1, p2, p3]);
  • p1、p2、p3 都是 Promise 实例,得到的 p 也是Promise 实例
  • Promise .all()方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。
  • p1、p2、p3 的状态都变成 fulfilled, p 的状态才会变成 fulfilled
  • p1、p2、p3 之中有一个被 rejected,p 的状态就变成 rejected
  • p 的 then 函数中得到的是 p1、p2、p3 的返回值组成的一个数组

promise.all 实战范例

import axios from 'axios'

let infoList = []

let id_list = ['1', '2', '3']

let promise_list = []

for (let id of id_list) {
  promise_list.push(axios.get(`http://jsonplaceholder.typicode.com/users/${id}`))
}

Promise.all(promise_list).then((res) => {
  infoList = res.map((item) => item.data)
  console.log(infoList) // 得到预期结果
})

手写 promise.all

function pAll (_promises) {
    return new Promise((resolve, reject) => {
      // Iterable => Array
      const promises = Array.from(_promises)
      // 结果用一个数组维护
      const r = []
      const len = promises.length
      let count = 0
      for (let i = 0; i < len; i++) {
        // Promise.resolve 确保把所有数据都转化为 Promise
        Promise.resolve(promises[i]).then(o => { 
          // 因为 promise 是异步的,保持数组一一对应
          r[i] = o;
  
          // 如果数组中所有 promise 都完成,则返回结果数组
          if (++count === len) {
            resolve(r)
          }
          // 当发生异常时,直接 reject
        }).catch(e => reject(e))
      }
    })
 }

Promise 自测题

此时仅创建了 Promise 对象,没有执行 resolve() 或 reject(),所以状态是 pending

因 setTimeout 是异步任务,内部代码在打印完 p2 后才执行,所以在打印 p2 时,Promise 还没执行 resolve() ,状态是 pending。

打印完 p2 后,setTimeout 内的 resolve() 执行,Promise 的状态变为 resolved

目录
相关文章
|
2月前
|
设计模式 监控 前端开发
并发设计模式实战系列(15):Future/Promise
🌟 大家好,我是摘星!🌟今天为大家带来的是并发设计模式实战系列,第十五章,废话不多说直接开始~
38 0
|
2月前
|
人工智能 自然语言处理 JavaScript
通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
通义灵码基于自然语言需求,快速生成完整Vue组件。例如,用Vue 2和JavaScript实现贪吃蛇游戏:包含键盘控制、得分系统、游戏结束判定与Canvas动态渲染。AI生成的代码符合规范,支持响应式数据与事件监听,还能进阶优化(如增加启停按钮、速度随分数提升)。传统需1小时的工作量,使用通义灵码仅10分钟完成,大幅提升开发效率。操作简单:安装插件、输入需求、运行项目即可实现功能。
146 4
 通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
|
6月前
|
存储 安全 API
Next.js 实战 (九):使用 next-auth 完成第三方身份登录验证
这篇文章介绍了next-auth,一个为Next.js设计的身份验证库,支持多种认证方式,如电子邮件和密码、OAuth2.0提供商(如Google、GitHub、Facebook等)以及自定义提供商。文章包含了如何配置Github Provider以及会话管理,并提到了适配器Adapters在next-auth中的作用。最后,文章强调了next-auth的强大功能值得进一步探索。
354 10
|
2月前
|
JSON 前端开发 Serverless
Mock.js 语法结构全解析
Mock.js 的语法规范介绍,从数据模板定义规范和数据占位符定义规范俩部分介绍, 让你更好的使用 Mock.js 来模拟数据并提高开发效率。
|
6月前
|
前端开发 JavaScript
Promise.allSettled()方法的语法是什么?
Promise.allSettled()方法的语法是什么?
241 79
|
6月前
|
前端开发
Promise.allSettled()和Promise.all()在处理错误时的差异是什么?
Promise.allSettled()和Promise.all()在处理错误时的差异是什么?
202 74
|
4月前
|
监控 JavaScript 前端开发
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
MutationObserver 是一个非常强大的 API,提供了一种高效、灵活的方式来监听和响应 DOM 变化。它解决了传统 DOM 事件监听器的诸多局限性,通过异步、批量的方式处理 DOM 变化,大大提高了性能和效率。在实际开发中,合理使用 MutationObserver 可以帮助我们更好地控制 DOM 操作,提高代码的健壮性和可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
|
6月前
|
中间件 API
Next.js 实战 (八):使用 Lodash 打包构建产生的“坑”?
这篇文章介绍了作者在使用Nextjs15进行项目开发时遇到的部署问题。在部署过程中,作者遇到了打包构建时的一系列报错,报错内容涉及动态代码评估在Edge运行时不被允许等问题。经过一天的尝试和调整,作者最终删除了lodash-es库,并将radash的部分源码复制到本地,解决了打包报错的问题。文章最后提供了项目的线上预览地址,并欢迎读者留言讨论更好的解决方案。
171 10
|
6月前
|
监控 安全 中间件
Next.js 实战 (十):中间件的魅力,打造更快更安全的应用
这篇文章介绍了什么是Next.js中的中间件以及其应用场景。中间件可以用于处理每个传入请求,比如实现日志记录、身份验证、重定向、CORS配置等功能。文章还提供了一个身份验证中间件的示例代码,以及如何使用限流中间件来限制同一IP地址的请求次数。中间件相当于一个构建模块,能够简化HTTP请求的预处理和后处理,提高代码的可维护性,有助于创建快速、安全和用户友好的Web体验。
147 0

热门文章

最新文章