当前位置: 首页 > news >正文

深入promise

深入promise

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

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

什么是Promise

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

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

如何创建 Promise

使用Promise 构造函数。

let promise = new Promise(function(resolve, reject) {
  // 当Promise初始化后会自动执行这个方法

  // 1s后返回done
  setTimeout(() => 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 的细微差别,并清楚地展示我们可能遇到的问题。

相关文章:

  • 苹果ios用户下载ipa文件内测签名的后的app应用下载安装到手机图标消失了-解决方案
  • SystemVerilog Assertions应用指南 第一章(1.25章节 “throughout”运算符)
  • 边端小场景音视频流分发架构
  • 【大数据】HBase入门指南
  • React知识点系列(8)-每天10个小知识
  • 数据特征选择 | Lasso特征选择(Python)
  • ElementUI--数据表格增删改查与表单验证
  • 数字IC/FPGA面试题目合集解析(一)
  • 机器学习-有监督学习-神经网络
  • Spring Boot中的Redis自动配置与使用
  • 消息称苹果或在明年推出搭载M3芯片的MacBook产品
  • XGBoost+LR融合
  • 如何使用JMeter测试导入接口/导出接口
  • frp隧道(流量代理)
  • uni-app:本地缓存的使用
  • 2023NOIP A层联测9 长春花
  • day62:ARMday9,I2c总线通信
  • Hi3516DV500 SVP_NNN添加opencv库记录
  • Idea执行Pom.xml导入jar包提示sun.misc.BASE64Encoder jar找不到---SpringCloud工作笔记197
  • Linux和UNIX的关系及区别
  • 央行设立服务消费与养老再贷款,额度5000亿元
  • 央行谈MLF:逐步退出政策利率属性回归流动性投放工具
  • 近4小时会谈、3项联合声明、20多份双边合作文本,中俄元首今年首次面对面会晤成果颇丰
  • 习近平抵达莫斯科对俄罗斯进行国事访问并出席纪念苏联伟大卫国战争胜利80周年庆典
  • 中国电信财务部总经理周响华调任华润集团总会计师
  • 科普|肩周炎的自限性,意味着不治也能自己好?