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

深度解读Promise.prototype.finally

由一个问题引发的血案:

手写源码实现Promise.prototype.finally。

我们知道,对于promise来讲,当状态敲定,无论状态兑现或拒绝时都需要调用的函数,可以使用Promise.prototype.finally的回调来实现。那么如何手写实现Promise.prototype.finally呢?问题恐怕并不很简单,本文主要做finally的细节和实现做一些详细的解读。

finally解决了什么问题

这可以让你避免在 promise 的 then() 和 catch() 处理器中重复编写代码。

以上为mdn中关于finally作用的解释。

finally的返回值

立即返回一个等效的 Promise 对象。

即finally返回的仍然是一个promise。

finally具体是怎么实现的

finally() 在内部调用其调用对象上的 then 方法。

这给了我们模拟实现finally的思路:即我们调用then方法即可:

Promise.prototype.finally = function (onFinally) {return this.then((value) => {},(err) => {});
}

finally回调接收什么参数

就Promise.prototype.finally(onFinally)而言:

onFinally 回调函数不接收任何参数。这种情况恰好适用于你不关心拒绝原因或兑现值的情况,因此无需提供它。

因此,我们可以对上面的代码增加回调执行,这只需要再then的两个回调中都调用即可,如下:

Promise.prototype.finally = function (onFinally) {return this.then((value) => {onFinally();});}, (err) => {onFinally();});
}

以上代码有一个问题:

即虽然我们实现了无论兑现或者拒绝都调用 onFinally回调,但是不能保证onFinally返回一个新的promise时,onFinally已经执行完毕。

解决方案是使用Promise.resolve包裹一层,如下:

Promise.prototype.finally = function (onFinally) {return this.then((value) => {Promise.resolve(onFinally()).then(() => {});}, (err) => {Promise.resolve(onFinally()).then(() => {});});
}

finally如何链式传递值

在上面的代码中,我们已经实现了无论promise兑现或拒绝都调用同一个回调,这看起来似乎已经达成了目标,但不要忘了,我们的finally仍然返回一个promise。

这个返回的promise如何接收之前的promise的值,又如何传递值给后面的promise,就成为了最重要的问题。

因此,工作还没有结束!对于返回值,mdn给出了说明:

返回等效的 Promise。如果处理程序抛出错误或返回被拒绝的 promise,那么 finally() 返回的 promise 将以该值被拒绝。否则,处理程序的返回值不会影响原始 promise 的状态。

  • finally() 调用通常是透明的,不会更改原始 promise 的状态。例如:
    • 与 Promise.resolve(2).then(() => 77, () => {}) 不同,它返回一个最终会兑现为值 77 的 promise,而 Promise.resolve(2).finally(() => 77) 返回一个最终兑现为值 2 的 promise。
    • 类似地,与 Promise.reject(3).then(() => {}, () => 88) 不同,它返回一个最终兑现为值 88 的 promise,而 Promise.reject(3).finally(() => 88) 返回一个最终以原因 3 拒绝的 promise。

 也就是说finally返回的新promise,与onFinally回调的返回值没有关系,而是透明传递之前的promise的值。因此上面的代码变为:

Promise.prototype.finally = function (onFinally) {return this.then((value) => {return Promise.resolve(onFinally()).then(() => {return value;});}, (err) => {return Promise.resolve(onFinally()).then(() => {throw err;});});
}

 关于三层return的解释

第一层return:finally的返回值。

通过调用then得到一个新的promise,并将其作为返回值。如果没有这个return,整个finally就没有返回值。

第二层return:then的返回值。

如果没有这个return,then将以undefined作为返回的promise的兑现值,这显然不符合预期。这里显然应该是返回一个新promise,新promise应该将之前的promise的值透明传递。

第三层return:新promise的传递值。

根据透明传递,因此对于value直接return value;对于err,则直接throw err;

全文完。

相关文章:

深度解读Promise.prototype.finally

由一个问题引发的血案: 手写源码实现Promise.prototype.finally。 我们知道,对于promise来讲,当状态敲定,无论状态兑现或拒绝时都需要调用的函数,可以使用Promise.prototype.finally的回调来实现。那么如何手写实现Pro…...

如何实现24/7客户服务自动化?建设智能客服知识库

客户自助服务是指用户通过企业或者第三方建立的网络平台或者终端,实现相关的自定义处理。实现客户服务自动化,对提高客户满意度、维持客户关系至关重要。客户服务自动化可以帮助企业以更快的速度和更高的效率来满足客户的售后服务要求,以进一…...

和鲸 ModelWhale 与中科可控多款服务器完成适配认证,赋能中国云生态

当前世界正处于新一轮技术革命及传统产业数字化转型的关键期,云计算作为重要的技术底座,其产业发展与产业规模对我国数字经济的高质量运行有着不可取代的推动作用。而随着我国数字上云、企业上云加快进入常规化阶段,云计算承载的业务应用越来…...

selenium +Jmeter 的性能测试

通过Jmeter快速将已有的Selenium 代码以性能测试的方式组织起来,并使用JMeter 丰富的报表展示测试结果 from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import By driver …...

探索高效的HTTP异步接口测试方法:从轮询等待到自动化方案

本文将深入探讨HTTP异步接口测试的多个方面,包括轮询等待、性能测试以及自动化方案。通过详细的解释和实际案例,帮助您了解如何有效地测试异步接口,确保系统的稳定性和性能。 在现代软件开发中,HTTP异步接口扮演着至关重要的角色&…...

Android资深工程书之LiveData核心组件原理剖析

LiveData是Android架构组件库中的一个类,用于在应用程序组件之间共享数据。它是一种可观察的数据持有者,可以感知应用程序组件的生命周期,并在数据发生变化时通知观察者。 使用LiveData 在Android应用程序中使用LiveData,你可以…...

Vue的五种方法实现加减乘除运算

五种方法的详细说明: 计算属性(Computed Properties): 计算属性是Vue.js提供的一种便捷的属性,它根据依赖的数据动态计算出一个新的值。计算属性的值会被缓存,只有当依赖的数据发生变化时,才会…...

C++(1)Linux基础知识

经济下行,计算机就业形势严峻,为了勉励自己继续进步,继续学习代码提高核心竞争力。 安装QT Creator 首先,安装QT开发工具QT Creator 参考:2021最新Qt6开发环境(Qt Creator)安装以及卸载记录_q…...

接口自动化yaml文件读取与写入

前言 在走进yaml文件之前大家应该都很想知道他是用来干嘛的? 是的是的,他是用来做接口自动化测试的。 我们一起来学习他吧!——(一定要收藏带走哦❤) 1、yaml文件有什么作用呢? ①可作为配置文件使用—…...

Java Map、JSONObject、实体类互转

文章目录 前言Map、JSONObject、实体类互转 前言 使用库 com.alibaba.fastjson2,可完成大部分JSON转换操作。 详情参考文章: Java FASTJSON2 一个性能极致并且简单易用的JSON库 Map、JSONObject、实体类互转 import com.alibaba.fastjson2.JSON; import com.alib…...

在Hive/Spark上执行TPC-DS基准测试 (PARQUET格式)

在上一篇文章:《在Hive/Spark上运行执行TPC-DS基准测试 (ORC和TEXT格式)》中,我们介绍了如何使用 hive-testbench 在Hive/Spark上执行TPC-DS基准测试,同时也指出了该项目不支持parquet格式。 如果我们想要生成parquet格式的测试数据,就需要使用其他工具了。本文选择使用另…...

基于CentOS搭建私有仓库harbor

环境: 操作系统:CentOS Linux 7 (Core) 内核: Linux 3.10.0-1160.el7.x86_64 目录 安装搭建harbor (1)安装docker编排工具docker compose (2)下载Harbor 安装包 (3&…...

PDF怎么转Word?8 个最佳 PDF 转 Word 转换器

PDF 转 Word 转换工具只是一个特殊程序,可以将 PDF(本机和/或扫描)转换为 Microsoft Office Word 格式。将 PDF 导出到 Word 的主要原因之一是满足可编辑文档的需求,尽管还有其他原因。 由于缺少 PDF 阅读器,您可以选…...

老板都爱看的财务数据分析报表,全在这了

老板们都爱看哪些财务数据分析报表?自然是可以帮助他们更好地了解公司的财务状况和经营绩效的那一类财务数据分析报表,比如利润表、资产负债表、现金流量表、应收账款分析报表、应付账款分析报表、库存分析报表等。奥威BI数据可视化工具有一套标准化财务…...

ZooKeeper(zk)与 Eureka 的区别及集群模式比较分析

​ 作者:zhaokk 推荐阅读 AI文本 OCR识别最佳实践 AI Gamma一键生成PPT工具直达链接 玩转cloud Studio 在线编码神器 玩转 GPU AI绘画、AI讲话、翻译,GPU点亮AI想象空间 资源分享 「java、python面试题」来自UC网盘app分享,打开手机app&#xff…...

搜狗拼音占用了VSCode及微信小程序开发者工具快捷键Ctrl + Shit + K 搜狗拼音截图快捷键

修改搜狗拼音的快捷键 右键--更多设置--属性设置--按键--系统功能快捷键--系统功能快捷键设置--取消Ctrl Shit K的勾选--勾选截屏并设置为Ctrl Shit A 微信开发者工具设置快捷键 右键--Command Palette--删除行 微信开发者工具快捷键 删除行:Ctrl Shit K 或…...

PMI-ACP值得考吗?在中国的前景如何?

相信很多小伙伴都听过PMP证书吧,但是对于PMI-ACP则知之甚少。那么同为项目管理证书,PMI-ACP认证的含金量怎么样呢?今天咱们就来聊一聊PMI-ACP敏捷项目管理证书。 PMI-ACP是由PMI(美国项目管理协会)颁发的针对敏捷项目…...

centos 安装防火墙,并开启对应端口号

1.查看防火墙状态: 命令:systemctl status firewalld.service 开启防火墙时,提示没有安装防火墙 [rootlocalhost ~]# systemctl start firewalld.service Failed to start firewalld.service: Unit not found.2.安装防火墙 [rootlocalhost …...

学习微信小程序时间延迟setTimeout和setInterval的使用方法

学习微信小程序时间延迟setTimeout和setInterval的使用方法 setTimeout()setInterval() setTimeout() setTimeout在使用的时候可以实现代码块延迟执行的效果,并且可以设置延迟执行的具体时间。请见如下代码: setTimeout(function() {//要实现延迟执行效…...

Vite好用的前端构建工具

是什么 Vite是Vue的作者尤雨溪开发的 一种新型前端构建工具。 Vite在大型项目开发模式下,打包速度远高于webpack。 Vite 为什么这么快 1. 快速冷启动 Vite只启动一台静态页面的服务器,不会打包全部项目文件代码,服务器根据客户端的请求加…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

大数据治理的常见方式

大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法&#xff0c;以下是几种常见的治理方式&#xff1a; 1. 数据质量管理 核心方法&#xff1a; 数据校验&#xff1a;建立数据校验规则&#xff08;格式、范围、一致性等&#xff09;数据清洗&…...

字符串哈希+KMP

P10468 兔子与兔子 #include<bits/stdc.h> using namespace std; typedef unsigned long long ull; const int N 1000010; ull a[N], pw[N]; int n; ull gethash(int l, int r){return a[r] - a[l - 1] * pw[r - l 1]; } signed main(){ios::sync_with_stdio(false), …...