深入promise

深入promise

我们可能知道如何使用 Promise,但是我们知道它们实际上是如何工作的吗?

为了让每个人都了解Promise,让我们从基础开始。如果我们知道 Promise 是什么以及如何使用它,我们可以跳过这一部分并直接跳到“魔法开始”的地方。

什么是Promise

当有人向我们询问一些我们现在没有的数据时,我们可以Promise稍后发送或在出现问题时发送错误。

因此Promise是一个代表异步操作最终完成或失败的对象。

如何创建 Promise

使用Promise 构造函数。

let promise = new Promise(function(resolve, reject) {// 当Promise初始化后会自动执行这个方法// 1s后返回donesetTimeout(() => resolve("done"), 1000);
});

传递给构造函数的函数称为“执行器”函数。它包含最终应产生结果的代码。创建new Promise 时,执行器会自动运行。

传递给执行器的resolve reject参数是 JavaScript 提供的函数。当我们准备好提供Promise结果时,请调用resolve ;如果出现问题,请调用reject

Promise 构造函数创建的promise对象具有以下属性:

  • state — 最初为 pending ,然后在调用resolve时更改为 fulfilled ,或者在调用reject时更改为 rejected
  • result — 最初为undefined,然后在调用resolve(value)时更改为value ,或者在调用reject(error)时更改为error

在这里插入图片描述

如何从Promise中获取实际数据?

我们可以使用then函数订阅承诺中的数据。

promise.then(function(result) { /* 处理成功的数据 */ },function(error) { /* 处理异常的数据 */ }
);

then的第一个参数是一个在 Promise 得到解决并接收结果时运行的函数。

then的第二个参数是一个在 Promise 被拒绝并收到错误时运行的函数。

then方法返回一个 Promise,这就是 Promise 可以被链式调用的原因:

promise.then(function(result) {  return someValue; },
).then(function(result2) { /* result2的值是someValue */ }
)

Promise 静态方法

Promise 对象有以下静态方法:

  • Promise.all(iterable) — 等待所有 Promise 得到解决,或者任何 Promise 被拒绝。
  • Promise.allSettled(iterable) — 等待所有 Promise 都已被处理(每个 Promise 都可以解决或拒绝)。
  • Promise.any(iterable) — 接受多个 Promise 对象,并且一旦对象中的一个Promise满足,就返回一个用该Promise的值解析。
  • Promise.race() — 等待任何Promise被解决或拒绝。
  • Promise.reject(reason) — 返回一个新的 Promise 对象,该对象因给定原因而被拒绝。
  • Promise.resolve() — 返回一个用给定值解析的 Promise 对象。如果该值是一个 Promisethenable对象,则返回该 Promise;否则,返回的promise将用该值来作为返回。

深入研究

我们将更深入地研究 Promise 的状态如何以及何时从“待处理”更改为“已完成”。

让我们创建一个简单的 Promise 对象,它立即解析一个普通值:

let promise = new Promise(function(resolve, reject) {resolve(5);
});
console.log(promise);

我们期望看到哪种状态?

没错,这是一个已解决的promise,值为 5。

现在,请记住Promise.resolve()用法示例:

Promise.resolve(Promise.resolve(5)) -> returnspromise<fulfilled>(5)

看看以下代码:


let promise = new Promise(function(resolve, reject) {resolve(Promise.resolve(5));
});console.log(promise);

我们希望再次看到Promise.resolve()已解决,对吧?

但是这个打印的promise将处于“待处理”状态。

现在考虑我们输出与上面示例相同的promise,但有延迟:

setTimeout(() => console.log(promise), 0);

此时的Promise 现在处于已解决。

让我们总结一下我们的实验结果:

  • Promise.resolve返回一个已解决的普通值的promise
  • 当传递的值是已解决的promise时, Promise.resolve返回已解决的promise
  • 传递给执行器的 resolve 函数返回一个已解决的promise
  • 当传递的值是已解决的 Promise 时,传递给执行器的 resolve 函数会返回一个挂起的 Promise
  • 当传递的值是已解决的Promise时,传递给执行器的解析函数的延迟结果是已解决的Promise

在这里插入图片描述

结论

显然Promise.resolve()resolve()的工作方式不同。

  • Promise.resolveresolve函数对于普通值的工作方式相同。两歌都返回了最终值。
  • Promise 作为参数传递时,Promise.resolveresolve函数的工作方式不同。当resolve以某种奇怪的方式工作时, Promise.resolve返回作为参数传递的相同的promise
  • resolve返回待处理Promise(不管这个Promise的状态如何),并且可能以某种异步方式更改返回的Promise状态。

这是否意味着当 Promise 作为参数传递时,resolve函数会异步工作?

为了理解这一点,让我们看一下 Promise 中肯定是异步工作的部分—— thencatchfinally函数。

我们可能听说过Promise 函数使用的是微任务队列。如果没有,让我们快速提醒一下。

当新的函数订阅 Promise 时,JavaScript 会将其放入微任务队列中。当 Promise 准备好(完成或拒绝)并且引擎不再处理同步代码时,JavaScript 会从微任务队列中逐一获取并调用回调。队列按照 FIFO 规则工作——“先进先出”。一般来说,微任务队列就像一个用于超时等的事件循环,但它具有更高的优先级。

在这里插入图片描述

resolve函数采用纯值作为参数时,它会立即执行。但是,如果参数是一个Promise(无论 Promise 的状态是什么),它就会订阅它,并将该函数放入微任务队列中 - 直到 Promise 准备好并且引擎可以自由地执行函数。这就是为什么我们不会立即得到一个已解决的Promise,而是在setTimeout中得到它。

规范中描述了此行为,感兴趣的可以去看看。

在本文中,我们试图揭示使用 Promise 的细微差别,并清楚地展示我们可能遇到的问题。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RSA加密与解密原理

目录 一、什么是RSA加密 二、RSA加密原理 三、RSA加解密过程与算法代码 一、什么是RSA加密 RSA加密是一种非对称加密算法。 对称加密&#xff1a; 对称加密是一种加密方式&#xff0c;加密和解密使用同一个密钥&#xff0c;被加密的信息在传输前用预先协商好的密钥进行加密…

KUKA机器人如何强制输出或取消数字IO信号?

KUKA机器人如何强制输出或取消数字IO信号? 具体的操作方法和步骤可参考以下内容: 如下图所示,点击菜单—显示—输入/输出端,如下图所示,选择想要查看的信号,这里以数字输出端为例进行说明, 如下图所示,此时可以看到输出端信号的编号、名称和当前值,可以通过下拉滚动条…

河北专升本(C语言)

目录 一&#xff1a;C语言的构成特点 二: 数据类型 三: 常量、变量、运算符及表达式 &#xff08;一&#xff09;标识符 &#xff08;二&#xff09;常量 &#xff08;三&#xff09;变量&#xff1a;其值可以改变的量 &#xff08;四&#xff09;各种类型数据混合运算 &…

简单好用的解压缩软件:keka 中文 for mac

Keka是一款功能全面、易于使用的文件压缩和解压缩软件&#xff0c;为Mac用户提供了便捷的文件管理工具。它支持多种压缩格式&#xff0c;具有快速解压和强大的压缩功能&#xff0c;让您能够轻松地处理各种文件压缩需求。 隐私非常重要 安全共享只需设置密码并创建高度加密的文…

深度强化学习 第 2 章 蒙特卡洛

2.1随机变量 强化学习中会经常用到两个概念&#xff1a; 随机变量、 观测值。 本书用大写字母表示随机变量&#xff0c;小写字母表示观测值&#xff0c;避免造成混淆。 下面我们定义概率质量函数&#xff08;probability mass function&#xff0c;缩写 PMF&#xff09;和概率…

LINUX定时解压缩方案

需求背景 对接客户中某个上游为外包系统&#xff0c;外包系统每日推送压缩文件至指定文件夹下&#xff0c;文件格式为YYYYMMDD_RegReport.zip。由于每日采集文件&#xff0c;无法对接压缩包内文件&#xff0c;需要将推送的压缩文件每日解压为文件夹 需求分析 与客户沟通后&a…

HarmonyOS 远端状态订阅开发实例

IPC/RPC 提供对远端 Stub 对象状态的订阅机制&#xff0c; 在远端 Stub 对象消亡时&#xff0c;可触发消亡通知告诉本地 Proxy 对象。这种状态通知订阅需要调用特定接口完成&#xff0c;当不再需要订阅时也需要调用特定接口取消。使用这种订阅机制的用户&#xff0c;需要实现消…

C++初阶(1)

W...Y的主页&#x1f60a; 代码仓库分享&#x1f495; ​ &#x1f354;前言&#xff1a; 今天我们正式进入C篇章&#xff0c;作为学过C语言的同志&#xff0c;继续学习C肯定就不会进行那些与C语言相同的学习&#xff0c;因为C语言的内容在C中也可以正常使用&#xff0c;所…

通过示例详细了解ES6导入导出模块

通过示例详细了解ES6导入导出模块 似乎许多开发人员认为 ES6 模块只不过是export、import关键字。事实上&#xff0c;它更加多样化。它拥有强大的功能和鲜为人知的问题。在本文中&#xff0c;我们将使用一些示例来了解这些内容。 示例一 // index.mjs import { default } fr…

flask vue跨域问题

问题&#xff1a; 调试时候跨域访问报&#xff1a; Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response. 解决办法&#xff1a; 安装flask_cros from flask_cors import CORS CORS(app) app.after_request def a…

如何避免大语言模型绕过知识库乱答的情况?LlamaIndex 原理与应用简介

本文首发于博客 LLM 应用开发实践 随着 LangChain LLM 方案快速普及&#xff0c;知识问答类应用的开发变得容易&#xff0c;但是面对回答准确度要求较高的场景&#xff0c;则暴露出一些局限性&#xff0c;比如向量查询方式得到的内容不匹配&#xff0c;LLM 对意图识别不准。所…

【Linux】多线程

文章目录 一.Linux线程概念1.什么是线程2.二级页表3.线程的优点4.线程的缺点5.线程异常6.线程用途 二.Linux进程VS线程1.进程和线程2.进程的多个线程共享3.进程和线程的关系 三.Linux线程控制1.POSIX线程库2.线程创建3.线程等待4.线程终止5.分离线程6.线程ID及进程地址空间布局…

手机拍摄的视频噪点很多怎么办,视频怎么做降噪处理?

现如今&#xff0c;智能手机已经成为了我们生活中必不可少的存在。而随着智能手机越来越强大&#xff0c;很多人已经开始使用手机来拍摄各种类型的视频。但是由于手机的限制&#xff0c;很多人会发现自己拍摄的视频存在着很多的噪点。那么&#xff0c;我们该怎样来解决拍摄视频…

N点复序列求2个N点实序列的快速傅里叶变换

一、方法简介 通过一个点复数序列求出两个点实数序列的离散傅里叶变换&#xff0c;进一步提升快速傅里叶变换的效率。 二、方法详解 和是实数序列&#xff0c;且长度都为&#xff0c;定义复数序列&#xff1a; &#xff0c; 则序列和可表示为&#xff1a; 的离散傅…

端到端的机器学习项目(Machine Learning 研习之六)

使用真实数据 当你在研习机器学习时&#xff0c;最好是使用真实世界中的数据&#xff0c;而不是采用人工数据。巧的是&#xff0c;数以千计的数据集可供选择&#xff0c;涵盖了各种领域。 流行的开放数据存储库&#xff1a; OpenML.orgKaggle.compaperswithcode.com UC Irvin…

MAYA教程之模型的UV拆分与材质介绍

什么是UV 模型制作完成后&#xff0c;需要给模型进行贴图&#xff0c;就需要用到UV功能 UV编译器介绍 打开UI编译器 主菜单有一个 UV->UV编译器&#xff0c;可以点击打开 创建一个模型&#xff0c;可以看到模型默认的UV UV编译器功能使用 UV模式的选择 在UV编译器中…

fastjson 1.2.47 远程命令执行漏洞

fastjson 1.2.47 远程命令执行漏洞 文章目录 fastjson 1.2.47 远程命令执行漏洞1 在线漏洞解读:2 环境搭建3 影响版本&#xff1a;4 漏洞复现4.1 访问页面4.2 bp抓包&#xff0c;修改参数 5 使用插件检测漏洞【FastjsonScan】5.1使用説明5.2 使用方法5.2.1 右键菜单中&#xff…

pycharm中快速对比两个.py文件

在学习一个算法的时候&#xff0c;就想着自己再敲一遍代码&#xff0c;结果最后出现了一个莫名其妙的错误&#xff0c;想跟源文件对比一下到底是在哪除了错&#xff0c;之前我都是大致定位一个一个对比&#xff0c;想起来matlab可以快速查找出两个脚本文件(.m文件)的区别&#…

Anylogic 读取和写入Excel文件

1、选择面板-连接-Excel文件&#xff0c;拖入到视图中 然后在excel文件的属性中进行绑定外部excel文件。 绑定完之后&#xff0c;在你需要读取的地方进行写代码&#xff0c; //定义开始读取的行数 //这里设为2&#xff0c;是因为第一行是数据名称 int row12; //读取excel文件信…

23面向对象案例1

目录 1、计算连续表达式的一个过程 2、优化后的代码 为什么不能return resultn&#xff1f; 3、用面向对象的方法可以解决冗余的问题&#xff0c;但是还是不能解决result的值可以被随意修改的问题 4、解决不能被随意修改的问题&#xff0c;可以将类属性改成私有变量吗&…