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

目录
相关文章
|
1月前
|
JavaScript
Nest.js 实战 (十一):配置热重载 HMR 给服务提提速
这篇文章介绍了Nest.js服务在应用程序引导过程中,TypeScript编译对效率的影响,以及如何通过使用webpackHMR来降低应用实例化的时间。文章包含具体教程,指导读者如何在项目中安装依赖包,并在根目录下新增webpack配置文件webpack-hmr.config.js来调整HMR相关的配置。最后,文章总结了如何通过自定义webpack配置来更好地控制HMR行为。
|
7天前
|
前端开发 JavaScript
JavaScript中的Promise:简化异步编程
JavaScript中的Promise:简化异步编程
|
24天前
Nest.js 实战 (十三):实现 SSE 服务端主动向客户端推送消息
这篇文章介绍了在Nest.js应用中使用Server-Sent Events (SSE)的技术。文章首先讨论了在特定业务场景下,为何选择SSE而不是WebSocket作为实时通信系统的实现方式。接着解释了SSE的概念,并展示了如何在Nest.js中实现SSE。文章包含客户端实现的代码示例,并以一个效果演示结束,总结SSE在Nest.js中的应用。
Nest.js 实战 (十三):实现 SSE 服务端主动向客户端推送消息
|
13天前
|
JavaScript 前端开发 安全
js逆向实战之烯牛数据请求参数加密和返回数据解密
【9月更文挑战第20天】在JavaScript逆向工程中,处理烯牛数据的请求参数加密和返回数据解密颇具挑战。本文详细分析了这一过程,包括网络请求监测、代码分析、加密算法推测及解密逻辑研究,并提供了实战步骤,如确定加密入口点、逆向分析算法及模拟加密解密过程。此外,还强调了法律合规性和安全性的重要性,帮助读者合法且安全地进行逆向工程。
54 11
|
9天前
|
Web App开发 前端开发 JavaScript
js之 Promise | 12-8
js之 Promise | 12-8
|
11天前
|
前端开发 JavaScript
ES6新标准下JS异步编程Promise解读
ES6新标准下JS异步编程Promise解读
19 3
|
12天前
|
前端开发 JavaScript
JavaScript Promise-2
JavaScript Promise-2
15 3
|
12天前
|
Web App开发 前端开发 JavaScript
JavaScript Promise-1
JavaScript Promise
14 3
|
24天前
|
JavaScript 前端开发
JS中Promise的类式实现写法
JS中Promise的类式实现写法
|
26天前
Nest.js 实战 (十二):优雅地使用事件发布/订阅模块 Event Emitter
这篇文章介绍了在Nest.js构建应用时,如何通过事件/发布-订阅模式使应用程序更健壮、灵活、易于扩展,并简化服务间通信。文章主要围绕@nestjs/event-emitter模块展开,这是一个基于eventemitter2库的社区模块,提供了事件发布/订阅功能,使得实现事件驱动架构变得简单。文章还介绍了如何使用该模块,包括安装依赖、初始化模块、注册EventEmitterModule、使用装饰器简化监听等。最后总结,集成@nestjs/event-emitter模块可以提升应用程序的事件驱动能力,构建出更为松耦合、易扩展且高度灵活的系统架构,是构建现代、响应迅速且具有高度解耦特性的Nest.