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

Promise魔鬼面试题

文章目录

    • 题目
    • 解析
      • 难点分析
      • 分析输出
        • step1
        • step2
        • step3
        • step4
        • step5
        • step6

参考/致谢:渡一袁老师

题目

Promise.resolve().then(() => {console.log(0);return Promise.resolve(4);}).then((res) => {console.log(res);});Promise.resolve().then(() => {console.log(1);}).then(() => {console.log(2);}).then(() => {console.log(3);}).then(() => {console.log(5);}).then(() => {console.log(6);});

解析

难点分析

  1. 这题难点就在于 return Promise.resolve(4) 当返回一个 Promise 的时候是如何处理的,在 Promise a+ 规范中,写道,如图:

    image-20240508012830269

  2. 也就是说这个当前Promise(表示return Promise了的当前这个Promise) 要与返回的 Promise 保持一致,但是如何保持一致,标准里面并没有说到,也就说实际如何实现这个状态一致,并不关心,在 v8 中,实现的源码如图:

    image-20240508013128678

  3. 表示的意思是如果返回的是 Promise,它会去调用这个 Promise 的 then 方法,在这个 then 方法里面完成当前 Promsie,但是调用 then 方法完成当前这个 Promise 是会放入到一个微任务队列里面去完成的

  4. 至此,这个难点就已经分析完成了

分析输出

step1

我们回到题目本身,来分析一下输出,我们知道,一个 then 方法一定会返回一个 Promise,then 方法是同步的,then 方法里面的回调才是异步的,根据这个准则,我们可以先来确定一下初步的执行状态。

根据这个准则,执行的初步顺序如下:

  1. 第一个 Promise.reslove():记作 pr1,状态为 fulfilled
  2. then(()=>{console.log(0)}):记作 p0,状态为 pending,因为这些then里面的回调函数还是异步任务,目前处于执行then方法的同步阶段,因此未执行也就无法确定 Promise 的状态,后续 pending 同理
  3. then((res)=>{console.log(res)}):记作 pres,状态为 pending
  4. 第二个 Promise.reslove():记作 pr2,状态为 fulfilled
  5. then(()=>{console.log(1)}):记作 p1,状态为 pending
  6. then(()=>{console.log(2)}):记作 p2,状态为 pending
  7. then(()=>{console.log(3)}):记作 p3,状态为 pending
  8. then(()=>{console.log(5)}):记作 p5,状态为 pending
  9. then(()=>{console.log(6)}):记作 p6,状态为 pending

图解如下:

image-20240508023258080

step2

此时同步执行完成,只有两个 Promise 状态完成,这两个函数开始执行,首先就会输出 0,然后根据前面分析的规则,如果返回的是一个 Promise,就会调用这个 Promise的then方法,且是放入一个微队列中执行,这里的 Promise.resolve(4) 记作 p4,那么使用一个伪代码表示即为 addMicrotask(p4.then(()=>完成p0)),为什么是完成呢?这里的返回的事 Promise.resolve(),所以在 then 里面是完成 p0,演变图解如下:

image-20240508023559162

step3

现在输出已经可以看到是 0,那么将微队列里面的任务开始执行,p1 的状态也会变为 fulfilled,然后将会输出 1,输出 1 之后

p1 变为 fulfilled 之后就会执行下一个 then 方法里面的成功回调,在这里也就是()=>{console.log(2)},而同理,这个回调也需要加入到微队列,即在 p4.then(()=>完成p0) 后加入

而 p4.then(()=>完成p0),其实需要执行只是()=>完成p0这一部分,then 方法里面的回调会加入到微队列,所以又会向后加入一个微任务,也就是在 ()=>{console.log(2)} 此回调后面,图解如下:

image-20240508023633702

step4

我们继续分析执行结果,执行p4.then(),将里面的回调加入到微队列,那么就会按照顺序执行 console.log(2),p2 变为 fulfilled,紧接着输出 2,输出 2 之后,同理将 ()=>{console.log(3)} 加入到微队列

执行 ()=>完成p0,会将 p0 的状态也变为 fulfilled,p0 变为 fulfilled 之后,就会把 p0 后续的 then(即pres) 加入到微队列,图解如下:

image-20240508024300933

step5

根据结果执行微队列里面的任务,同理 p3 也变为 fulfilled,然后就会输出 3,同时将 p3 下一个 then 方法的回调(即p5)加入到微队列。

然后执行 (res)=>{console.log(res)},同理 pres 状态为 fulfilled,控制台输出 4

res 为什么是 4?Promise a+ 规范,如果返回的是 promise,则下一个 then 方法的执行的回调和结果由这个返回的 Promise 决定,图解如下:

image-20240508025843267

step6

那后续的输出就是一样的了,输出 5,同理 p5 的状态为 fulfilled,将 p6 的回调加入微队列,然后执行,输出 6,完成 p6,最后程序执行结果如图:

image-20240508030258847

相关文章:

Promise魔鬼面试题

文章目录 题目解析难点分析分析输出step1step2step3step4step5step6 参考/致谢:渡一袁老师 题目 Promise.resolve().then(() > {console.log(0);return Promise.resolve(4);}).then((res) > {console.log(res);});Promise.resolve().then(() > {console.l…...

Vue3+Nuxt3 从0到1搭建官网项目(SEO搜索、中英文切换、图片懒加载)

Vue2Nuxt2 从 0 到1 搭建官网~ Vue3Nuxt3 从0到1搭建官网项目 安装 Nuxt3,创建项目初始化的 package.json项目结构初始化项目pages 文件下创建index.vue引入sass修改 app.vue 文件查看效果 配置公共的css、metaassets下的cssreset.scss 重置文件common.scss 配置nux…...

面试经典150题——三数之和

面试经典150题 day29 题目来源我的题解方法一 暴力解法 超时方法二 扩展两数之和(双指针)方法三 扩展为通用的n数之和 题目来源 力扣每日一题;题序:15 我的题解 方法一 暴力解法 超时 进行三重循环遍历,判断和是否为…...

go动态创建/增加channel并处理数据

背景描述 有一个需求,大概可以描述为:有多个websocket连接,因此消息会并发地发送过来,这些消息中有一个标志可以表明是哪个连接发来的消息,但只有收到消息后才能建立channel或写入已有channel,在收消息前无…...

asp.net成绩查询系统

说明文档 运行前附加数据库.mdf(或sql生成数据库) 主要技术: 基于asp.net架构和sql server数据库 功能模块: asp.net成绩查询系统 学生功能有查看成绩和修改账号密码等 后台管理员可以进行用户管理 管理员添加管理员查询注…...

Express路由

什么是路由 官方定义&#xff1a;路由确定了应用程序如何响应客户端对特定端点的请求。 路由的使用 一个路由的组成有 请求方法、路径 和 回调函数 组成。 Express中提供了一些列方法&#xff0c;可以很方便的使用路由&#xff0c;使用格式如下&#xff1a; app.<metho…...

在做题中学习(53): 寻找旋转数组中的最小值

153. 寻找旋转排序数组中的最小值 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a;O(logn)->很可能就是二分查找 思路&#xff1a;再看看题目要求&#xff0c;可以画出旋转之后数组中元素的大小关系&#xff1a; 首先&#xff0c;数组是具有二段性的(适配二分查…...

C#语言进阶(三) 元组

总目录 C# 语法总目录 元组目录 元组1. 元组元素命名2. 元组的解构3. 元组的比较 元组 元组(tuple)是一组存储值的便捷方式。 元组的目的主要是&#xff0c;不使用out参数而从方法中返回多个值。(匿名类型无法做这个操作)元组能做匿名类型所有操作。 元组是值类型&#xff0…...

实用的Chrome 浏览器命令

Google Chrome 浏览器提供了许多快捷命令和实用功能&#xff0c;可以帮助用户提高效率和改善浏览体验。这里列举了一些非常实用的Chrome浏览器命令&#xff1a; 1. **CtrlT** / **CmdT** - 打开一个新的标签页。 2. **CtrlShiftT** / **CmdShiftT** - 重新打开最后关闭的标签页…...

IDEA远程连接docker服务,windows版docker desktop

1.windows上安装docker desktop docker desktop下载地址&#xff1a;Docker Desktop: The #1 Containerization Tool for Developers | Docker 有的windows系统不支持安装docker desktop 安装完之后我们可以直接打开&#xff0c;可以选择不登录使用 我们用IDEA连接到docker …...

Rust 和 Go 哪个更好?

在讨论 Rust 与 Go 两种编程语言哪种更优秀时&#xff0c;我们将探讨它们在性能、简易性、安全性、功能、规模和并发处理等方面的比较。同时&#xff0c;我们看看它们有什么共同点和根本的差异。现在就来看看这个友好而公平的对比。 Rust 和 Go 都是优秀的选择 首先&#xff…...

【免费Java系列】大家好 ,今天是学习面向对象高级的第八天点赞收藏关注,持续更新作品 !

这是java进阶课面向对象第一天的课程可以坐传送去学习http://t.csdnimg.cn/Lq3io day08-Map集合、Stream流、File类 一、Map集合 同学们&#xff0c;在前面几节课我们已经学习了Map集合的常用方法&#xff0c;以及遍历方式。 下面我们要学习的是Map接口下面的是三个实现类H…...

RPC 失败。curl 16 Error in the HTTP2 framing layer

报错&#xff1a; (base) hh-virtual-machine:~/work$ git clone https://github.com/yangzongzhuan/RuoYi-Vue3.git 正克隆到 RuoYi-Vue3... error: RPC 失败。curl 16 Error in the HTTP2 framing layer fatal: 在引用列表之后应该有一个 flush 包这个错误通常是由于 Git 在…...

(图论)最短路问题合集(包含C,C++,Java,Python,Go)

不存在负权边&#xff1a; 1.朴素dijkstra算法 原题&#xff1a; 思路&#xff1a;&#xff08;依然是贪心的思想&#xff09; 1.初始化距离&#xff1a;dis[1]0&#xff0c;dis[i]INF&#xff08;正无穷&#xff09; 2.循环n次&#xff1a; 找到当前不在s中的dis最小的点&…...

电脑文件批量重命名不求人:快速操作,高效技巧让你轻松搞定

在数字化时代&#xff0c;电脑文件的管理与整理显得尤为重要。当面对大量需要重命名的文件时&#xff0c;一个个手动修改不仅耗时&#xff0c;还容易出错。那么&#xff0c;有没有一种方法可以快速、高效地完成这一任务呢&#xff1f;答案是肯定的&#xff0c;下面就来介绍几种…...

基于springboot的网上点餐系统源码数据库

基于springboot的网上点餐系统源码数据库 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于网上点餐系统当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了网上点餐系统…...

mysql cluster数据库集群介绍、部署及配置

前言: MySQL集群是一个无共享的、分布式节点架构的存储方案,旨在提供容错性和高性能。它由三个主要节点组成:管理节点(MGM)、数据节点和SQL节点。 管理节点(MGM) 定义与用途:管理节点是MySQL Cluster的控制中心,负责管理集群内的其他节点。它提供配置数据,启动和停止…...

uniapp的app端软件更新弹框

1&#xff1a;使用html PLUS实现&#xff1a;地址HTML5 API Reference (html5plus.org)&#xff0c;效果图 2&#xff1a;在app.vue的onLaunch生命周期中&#xff0c;代码如下&#xff1a; onLaunch: function() {let a 0let view new plus.nativeObj.View(maskView, {backg…...

win11 Terminal 部分窗口美化

需求及分析&#xff1a;因为在 cmd、anaconda prompt 窗口中输入命令较多&#xff0c;而命令输入行和输出结果都是同一个颜色&#xff0c;不易阅读&#xff0c;故将需求定性为「美化窗口」。 美化结束后&#xff0c;我在想是否能不安装任何软件&#xff0c;简单地通过调整主题颜…...

开源go实现的iot物联网新基建平台

软件介绍 Magistrala IoT平台是由Abstract Machines公司开发的创新基础设施解决方案&#xff0c;旨在帮助组织和开发者构建安全、可扩展和创新的物联网应用程序。曾经被称为Mainflux的平台&#xff0c;现在已经开源&#xff0c;并在国际物联网领域受到广泛关注。 功能描述 多协…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...

上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式

简介 在我的 QT/C 开发工作中&#xff0c;合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式&#xff1a;工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...

全面解析数据库:从基础概念到前沿应用​

在数字化时代&#xff0c;数据已成为企业和社会发展的核心资产&#xff0c;而数据库作为存储、管理和处理数据的关键工具&#xff0c;在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理&#xff0c;到社交网络的用户数据存储&#xff0c;再到金融行业的交易记录处理&a…...