JavaScript系列——Promise

文章目录

    • 概要
    • Promise三种状态
    • 状态改变
    • Promise链式调用
    • Promise处理并发
      • promise.all()
      • promise.allSettled()
      • Promise.any()
      • promise.race()
    • 小结

概要

Promise中文翻译过来就是承诺、预示、有可能的意思。
在JavaScript里面,Promise 是一个对象,表示异步操作最终成功或失败返回的结果值

promise 是一个代理,创建promise对象时,我们不知道异步处理会返回什么值。promise将异步操作下可能发生不同的操作结果事先制定处理逻辑,将其不同状态的值返回出来。这使得异步方法可以像同步方法一样返回值。

使用Promise的不会立即返回异步方法处理的结果值,而是返回一个Promise对象,等待某个合适时机后,通过promise获取对应的结果值。promise对象,可能有以下三种状态,下面详细说明一下

Promise三种状态

  • 待定(pending):初始状态,既没有被兑现,也没有被拒绝
  • 已兑现(fulfilled):意味着操作成功完成。
  • 已拒绝(rejected):意味着操作失败

一个待定状态的Promise,最终状态可以是已兑现并返回一个值,或者是已拒绝并返回一个错误原因

当其中任意一种情况发生时,通过Promise 的then 方法串联的处理程序将会立即调用。

promise对象的状态是不可逆的,一旦其被兑现或者拒绝,即不再处于待定状态,那么则称之为已敲定(settled)
在这里插入图片描述

我们还会听到使用已解决(resolved)这个术语来描述 Promise——这意味着该 Promise 已经敲定(settled),或为了匹配另一个 Promise 的最终状态而被“锁定(lock-in)”,进一步解决或拒绝它都没有影响。

例如以下代码示例:

new Promise((resolveOuter) => {
  resolveOuter(
    new Promise((resolveInner) => {
      setTimeout(resolveInner, 1000);
    }),
  );
});

此 Promise 在创建时已经被解决(因为 resolveOuter 是同步调用的),但它是用另一个 Promise 解决的,因此在内部 Promise 兑现的 1 秒之后才会被兑现,在此之前,一直处于待定状态。在实践中,“解决”过程通常是在幕后完成的,不可观察,只有其兑现或拒绝是可观察的。

状态改变

Promise 对象,可以使用new 关键字进行实例化,语法如下:

new Promise(executor)

Promise() 只能通过new运算符来构造
如果尝试在没有使用 new 的情况下调用它,会抛出 TypeError 异常·。

executor 表示在构造函数中执行的函数,
它接受两个函数作为参数:resolveFunc 和 rejectFunc
其中,executor 中抛出任何错误都会导致Promise 被拒绝,并且返回值被忽略。

executor 是将回调函数的结果与 Promise 关联在一起的自定义代码。编写 executor 的工作由程序员完成。它的函数签名如下面代码所示:

function executor(resolveFunc, rejectFunc) {
  // 通常,`executor` 函数用于封装某些接受回调函数作为参数的异步操作,比如上面的 `readFile` 函数
}

executor 执行与Promise 的对象构造是同步进行的。但作为executor 函数的参数的函数resolutionFunc 和rejectionFunc,一般 要结合异步函数的操作结果来决定调用谁。

resolutionFunc 或者 rejectionFunc 被调用时,另一个 Promise 对象作为函数参数的话,该 Promise 对象就会变为已解决(resolved)。但仍未“敲定(settled)”的待定状态。解决状态下的Promise不一定会导致Promise变成已兑现或者拒绝状态,最终要看作为参数的Promise 状态。

如果调用resolutionFunc (传入参数不是Promise ),Promise 将会成为被兑现(fulfilled)状态
如果调用rejectFunc (传入参数不是Promise ),Promise 对象将会成为拒绝(rejected)状态

成为被兑现或拒绝状态Promise ,都是敲定状态的Promise

只有第一次调用 resolveFunc 或 rejectFunc 会影响 Promise 的最终状态,随后对任一函数的调用都不能更改兑现值或拒绝原因,也不能将其最终状态从“已兑现”转换为“已拒绝”或相反。

一旦 Promise 敲定,它会(异步地)调用任何通过 then()、catch() 或 finally() 关联的进一步处理程序。最终的兑现值或拒绝原因在调用时作为输入参数传给兑现和拒绝处理程序。

Promise链式调用

Promise 原型有三个方法,用于将进一步的操作与已敲定的 Promise 相关联,都是可以返回Promise 对象,因此,他们可以进行串联,形成链式调用,他们分别是:

  • Promise.prototype.then()
    将一个处理兑换或者处理拒绝的处理器附加到Promise 上,并返回Promise。无论Promise 是否被兑现还是被拒绝,处理器都会在Promise敲定时被调用
  • Promise.prototype.catch()
    将一个拒绝处理回调函数附加到 Promise 上,并返回Promise,如果回调被调用,则解决回调的返回值
  • Promise.prototye.finally()
    将一个处理器附加到 Promise 上,并返回Promise,当原始 Promise 被解决时解决。无论 Promise 是否被兑现还是被拒绝,处理器都会在 Promise 敲定时被调用

其中,then 方法最多可以接受两个参数,第一个参数为Promise兑现时的回调函数,第二个参数是Promise 拒绝时的回调函数,每一个then 返回Promise 对象,这个对象可以被用于链式调用,例如以下代码

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("foo");
  }, 300);
});

myPromise
  .then(handleFulfilledA, handleRejectedA)
  .then(handleFulfilledB, handleRejectedB)
  .then(handleFulfilledC, handleRejectedC);

myPromise 经过第一个then 方法被捕捉后,依然可以再使用then 来处理第一个then 方法返回promise。

then 方法在 可以省略返回promise 对象的回调函数,程序仍会继续链接到下一个链式调用。在最终的.catch()之前,可以安全地省略每个链式调用中处理已拒绝状态的回调函数,如下面的代码示例:

myPromise
  .then(handleFulfilledA)
  .then(handleFulfilledB)
  .then(handleFulfilledC)
  .catch(handleRejectedAny);

如果在某一个then 调用中,需要急切处理错误,那么这种情况需要在then中声明对应的拒绝回调函数。如果不是那么急切,可以在最后使用catch进行捕捉。

一个的Promise的终止条件(返回值条件)决定调用链中下一个Promise的“已敲定”状态。

链中每个已兑现的 Promise 的返回值会传递给下一个 .then(),而已拒绝的 Promise 会把失败原因传递给链中下一个拒绝处理函数。

例如如下代码:

const myPromise = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("foo");
      // reject("foo");
    }, 300);
  });

  myPromise
  .then((value) => `${value} and bar`)
  .then((value) => `${value} and bar again`)
  .then((value) => `${value} and again`)
  .then((value) => `${value} and again`)
  .then((value) => {
    console.log(value);
  })
  .catch((err) => {
    console.error(err);
  });

myPromise 延迟300毫秒后,调用resolveFunc,myPromise 变成已兑现状态,并传入了foo作为函数函数。
紧接着,第一个then被触发调用,value=foo,在第一个then 中,拼接了myPromise 返回值,并返回foo and bar
同理,最后console.log(value);输出的语句为foo and bar and bar again and again and again,即把myPromise 进过各个then串联处理。
每一个then 执行后,返回的Promise 依然是一开始的已兑现状态的myPromise

如下代码:

  myPromise.then().then().then(res=>{
    console.log(res,myPromise.then())
  }).catch(err=>console.log(err))

输出结果,myPromise.then(),依然是已兑现状态的myPromise。
在这里插入图片描述

Promise处理并发

Promise 类还提供了四个静态方法来处理任务的并发

  • Promise.all()
    在所有传入的Promise,全部被兑现兑现任意一个Promise被拒绝都会拒绝
  • Promise.allSettled()
    在所有的Promise 都被敲定(所有状态成已经成功或拒绝)时兑现
  • Promise.any()
    任意一个Promise 被兑现兑现,仅仅在所有的Promise 都拒绝时才会拒绝
  • Promise.race()
    任意一个Promise被敲定时敲定。也就是任意一个Promise 被兑现时被兑现或者任意一个Promise被拒绝时拒绝

以上的所有方法,都是接受一个Promise的可迭代对象,并返回一个新的Promise。

代码示例如下

promise.all()

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});
// Expected output: Array [3, 42, "foo"]

promise.allSettled()

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) =>
  setTimeout(reject, 100, 'foo'),
);
const promises = [promise1, promise2];

Promise.allSettled(promises).then((results) =>
  results.forEach((result) => console.log(result.status)),
);

// Expected output:
// "fulfilled"
// "rejected"

Promise.any()

const promise1 = Promise.reject(0);
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, 'quick'));
const promise3 = new Promise((resolve) => setTimeout(resolve, 500, 'slow'));

const promises = [promise1, promise2, promise3];

Promise.any(promises).then((value) => console.log(value));

// Expected output: "quick"

promise.race()

const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, 'one');
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'two');
});

Promise.race([promise1, promise2]).then((value) => {
  console.log(value);
  // Both resolve, but promise2 is faster
});
// Expected output: "two"

小结

  • Promise 对象可以将异步操作结果进行返回,值可能是异步成果的结果或错误原因
  • Promise 对象有三种状态,待定、被兑现、拒绝
  • 构造Promise会同步执行executor,他需要两个函数作为参数,rejectFunc 和resolveFunc
  • rejectFunc 和resolveFunc调用传入非Promise 对象时,状态会变成已兑现或拒绝的敲定状态
  • 变成敲定状态的Promise,会调用Promise串联的then方法
  • 串联Promise ,调用then()方法返回的是的已敲定的原Promise对象,then回调函数参数值,是上一个函数的返回值
  • Promise执行后,不可以取消和暂停,如果想要达到按照自己节奏来执行异步操作,可以使用generator,它可以操作一步一步来,后续会出文章详细说明。关于generator文章点击这个

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/320935.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023年山东省职业院校技能大赛高职组信息安全管理与评估 理论题(正式赛)

2023年山东省职业院校技能大赛高职组信息安全管理与评估 理论题 理论技能与职业素养(100分) 2023年山东省职业院校技能大赛高职组信息安全管理与评估 理论题 【注意事项】 Geek极安云科专注技能竞赛技术提升,基于各大赛项提供全面的系统性…

【JAVA】哪些集合类是线程安全的

🍎个人博客:个人主页 🏆个人专栏:JAVA ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 Vector: HashTable: Collections.synchronizedList()、Collections.synchronizedSet()、Collections.syn…

网络地图服务(WMS)详解

文章目录 1.概述2.GetCapabilities3.GetMap4.GetFeatureInfo 阅读本文之前可参考前文:《地图服务器GeoServer的安装与配置》与《GeoServer发布地图服务(WMS、WFS)》。 1.概述 经过前文的介绍,相信我们对WMS/WFS服务已经有了一个非…

收银系统源码收银系统OEM定制开发(收银POS+线上商城+ERP+营销插件+聚合支付)

源码:零售行业线下线上一体化收银系统 1.开发语言 核心开发语言: php、HTML5、JavaPHP开发环境:php7.3安卓端收银、助手: 原生的JavaPC收银端: HTML5vuecssjsnwjs微信小程序助手: 原生小程序开发商城: uniapp后合管理网站: HTML5vueelement-uicssjs 2…

基于Java SSM框架实现在线作业管理系统项目【项目源码】计算机毕业设计

基于java的SSM框架实现在线作业管理系统演示 JSP技术 JSP技术本身是一种脚本语言,但它的功能是十分强大的,因为它可以使用所有的JAVA类。当它与JavaBeans 类进行结合时,它可以使显示逻辑和内容分开,这就极大的方便了运动员的需求…

day01

文章目录 创建Vue实例插值表达式响应式数据常见标签v-htmlv-show v-ifv-if v-else-if v-elsev-onv-bindv-forv-model 综合案例 创建Vue实例 <!--创建Vue实例&#xff0c;初始化渲染1. 准备容器2. 引包&#xff08;官网&#xff09; — 开发版本/生产版本3. 创建Vue实例 ne…

配置DNS

vim /etc/named.conf vim /etc/named.rfc1912.zones cp named.localhost ./kgc.com.zone -p vim kgc.com.zone 设置备用dns服务器 修改主配置文件&#xff0c;并自动同步到从服务器

Zung氏焦虑症测试SAS

SAS被称为焦虑自评量表&#xff0c;是一种用来测量焦虑症状程度以及观察治疗过程中变化情况的心理量表。主要用于评估心理状态&#xff0c;辅助参考数据&#xff0c;也是焦虑评定的标准。焦虑自评量表系是由William W.K. Zung编制的&#xff0c;该量表已成为心理咨询师、心理医…

COBOL语言 :一种主要专注于解决业务问题的编程语言

译文&#xff1a; 什么是COBOL? COBOL是一种主要专注于解决业务问题的编程语言。COBOL的完整形式是面向业务的通用语言。它主要用于公司和政府的商业、金融和行政系统。这种语言也被用来解决许多数据处理问题。 它是由CODASYL(数据系统语言会议)开发的。它被用作大型机中的一…

解决报错:AttributeError: module ‘torch‘ has no attribute ‘_six‘

报错代码&#xff1a; if torch._six.PY3:import importlibimport importlib.utilimport sys这里的意思是判断你的python版本是否是python3&#xff0c;如果是PY37&#xff0c;就是判断你的python版本是不是python3.7&#xff0c;源码&#xff1a; PY37 sys.version_info[0]…

Keil5如何生成反汇编文件

Keil5如何生成反汇编文件 在Keil5界面下点击选项&#xff0c;选择“User”&#xff0c;勾选“After Build/Rebuild”中“RUN #1”&#xff0c;复制fromelf --text -a -c --outputxxx.dis xxx.axf 在Linker栏中找到“Linker Control string”里最后-o后的.axf文件&#xff0c;将…

街机模拟游戏逆向工程(HACKROM)教程:[1]数据的存储与读取

简介 在计算机中&#xff0c;数据存储的介质一直在变化&#xff0c;从最早的穿孔纸带&#xff0c;到现在的固态硬盘。但存储的原理是一直没有变化的&#xff0c;在计算机中&#xff0c;我们所存储的数据&#xff0c;一直都是以二进制的形式被存储存在不同的介质中。 计算机用…

Jenkins基础篇--凭据(Credential)管理

什么是凭据 Jenkins的Credentials直译为证书、文凭&#xff0c;我们可以理解为它是钥匙&#xff0c;用来做某些事情的认证。 如Jenkins 和 GitLab交互时&#xff0c;需要添加GitLab的API令牌和登录凭证。 如Jenkins 添加从节点时&#xff0c;需要添加从节点的登录凭证或者Je…

Linux的DHCP工作原理和dns服务器

目录 一、DHCP原理 1.DHCP的好处 2.DHCP的分配方式 3.实验 二、dns服务器 1.什么是dns 2.dns域名解析 3、在内网搭建dns 一、DHCP原理 DCHP工作原理使用C/S架构 &#xff08;1&#xff09;第一步&#xff0c;客户端广播发送一个discover报文寻找DHCP服务器。 &#…

网络爬虫丨基于requests+mysql爬取猫眼热门电影数据做可视化分析

文章目录 写在前面实验描述实验内容遇到问题 写在后面 写在前面 本期内容&#xff1a;基于requestsmysql爬取猫眼热门电影数据做可视化分析 实验需求 anaconda丨pycharmpython3.11.4requestsmysql 项目下载地址&#xff1a;https://download.csdn.net/download/m0_68111267…

OceanBase 4.2特性解读:Show Trace全链路跟踪,助力快速问题定位与精准诊断

在分布式数据库环境下&#xff0c;慢 SQL 诊断是运维人员面临的一大挑战。在无法及时发现问题根本原因的情况下&#xff0c;可能会严重影响用户体验&#xff0c;甚至会导致业务服务不可用。相对于单机数据库&#xff0c;分布式数据库系统涉及多个节点、多组件的协同工作&#x…

苍穹外卖学习----出错记录

1.微信开发者工具遇到的问题&#xff1a; 1.1appid消失报错&#xff1a; {errMsg: login:fail 系统错误,错误码:41002,appid missing [20240112 16:44:02][undefined]} 1.2解决方式&#xff1a; appid可在微信开发者官网 登录账号后在开发栏 找到 复制后按以下步骤粘贴即…

玩转 openEuler (一)-- 系统安装

简介 openEuler 是一款开源操作系统。当前 openEuler 内核源于Linux&#xff0c;支持鲲鹏及其它多种处理器&#xff0c;能够充分释放计算芯片的潜能&#xff0c;是由全球开源贡献者构建的高效、稳定、安全的开源操作系统&#xff0c;适用于数据库、大数据、云计算、人工智能等…

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例4-1 表单

代码 <!doctype html> <html> <head> <meta charset"utf-8"> <title>表单</title> </head><body> <!--<form action"URL地址" method"提交方式" name"表单名称" /*编码“多部…

GPT实战系列-简单聊聊LangChain搭建本地知识库准备

GPT实战系列-简单聊聊LangChain搭建本地知识库准备 LangChain 是一个开发由语言模型驱动的应用程序的框架&#xff0c;除了和应用程序通过 API 调用&#xff0c; 还会&#xff1a; 数据感知 : 将语言模型连接到其他数据源 具有代理性质 : 允许语言模型与其环境交互 LLM大模型…