深入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;被加密的信息在传输前用预先协商好的密钥进行加密…

[JVM]问下,对象在堆上的内存分配是怎样的

Java 技术体系的自动内存管理,最根本的目标是自动化地解决两个问题:自动给对象分配内存以及自动回收分配给对象的内存 这里面最重要的就是,对象在堆上的内存分配 这篇文章来具体讲讲 堆整体上来说,主要分为 新生代 & 老年代 新生代又分为: Eden 区和 Survivor 区, Survivo…

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

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

河北专升本(C语言)

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

Java实现快速排序

1.介绍 快排分为两种: 1.lomuto分区算法 (快慢指针)(单边) 2.Hoare分区算法 (前后指针)(双边) 快排主要思想:选一个基准元素分为两部分,先让左边排一下序再让右边排序 2.思路分析 1.lomuto分区算法 默认&#xff1a;最右边的元素作为基准点 1.设置两个指针(dest , cu…

【Java】工具类的设计

工具类设计思想 构造方法用 private 修饰 外部无法new成员方法使用 public static 修饰 通过类名称 . 方法名称 访问 示例代码&#xff1a; Test11_1.java&#xff1a;设计一个工具类 package com.api.Demo07;import java.util.Arrays;public class Test11_1 {/*** 将数组中 …

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

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

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

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

mkdir-创建目录文件

mkdir命令来自英文词组”make directories“的缩写,其功能是用来创建目录文件。使用方法简单,但需要注意若要创建的目标目录已经存在,则会提示已存在而不继续创建,不覆盖已有文件。 语法格式:mkdir [参数] 目录名 参数说明-m创建目录的同时设置权限-p递归创建多级目录-v显…

课程表系列

相关题目&#xff1a; 207. 课程表 210. 课程表 II 1462. 课程表 IV class CourseSchedule:"""207.课程表https://leetcode.cn/problems/course-schedule/"""def __init__(self):# 记录⼀次递归堆栈中的节点self.onPath []# 记录遍历过的节点&…

LINUX定时解压缩方案

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

Kafka知识补充

如何避免 Rebalance 最简单粗暴的就是 &#xff1a; 减少组成员数量发生变化 每个 Consumer 实例都会定期地向 Coordinator 发送心跳请求&#xff0c;表明它还存活着。如果某个 Consumer 实例不能及时地发送这些心跳请求&#xff0c;Coordinator 就会认为该 Consumer 已经“死…

HarmonyOS 远端状态订阅开发实例

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

Tensorflow2 中对模型进行编译,不同loss函数的选择下输入数据格式需求变化

一、tf2中常用的损失函数介绍 在 TensorFlow 2 中&#xff0c;编译模型时可以选择不同的损失函数来定义模型的目标函数。不同的损失函数适用于不同的问题类型和模型架构。下面是几种常见的损失函数以及它们的作用和适用场景&#xff1a; 1.均方误差&#xff08;Mean Squared …

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…

标准误与聚类稳健标准误的理解

1 标准误 1.1 定义 标准误&#xff08;Standard Error&#xff09;是用来衡量统计样本估计量&#xff08;如均值、回归系数等&#xff09;与总体参数之间的差异的一种统计量。标准误衡量了样本估计量的变异程度&#xff0c;提供了对总体参数的估计的不确定性的度量。标准误越…

动网格模型算法基础(二)

本贴主要简述动网格模型算法 FLUENT动网格模型能够根据用户指定的边界运动、网络类型和网格再生方式自动地调节内部体网格节点的位置。 一、动网格使用面临的量大问题&#xff1a; 体网格的再生&#xff1b;边界运动或变形的指定&#xff1b; 二、体网格再生方法&#xff1…

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 对意图识别不准。所…