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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于FPGA的数字信号处理(10)--定点数的舍入模式(1)四舍五入round

1、前言 将浮点数定量化为定点数时,有一个避不开的问题:某些小数是无法用有限个数的2进制数来表示的。比如: 0.5(D) 0.1(B) 0.1(D) 0.0001100110011001~~~~(B) 可以看到0.5是可以精准表示的,但是0.1却不行。原因是整数是离散的…

AngusTester安装请求代理

一、介绍 请求代理程序(AngusProxy)提供两个方面作用: 代理Http和WebSocket协议接口调试请求,解决浏览器跨域限制问题。对代理请求客户化处理支持,允许用户对代理请求进行二次处理,如:请求参数签名。 二、类型 为了…

【经验01】spark执行离线任务的一些坑

项目背景: 目前使用spark跑大体量的数据,效率还是挺高的,机器多,120多台的hadoop集群,还是相当的给力的。数据大概有10T的量。 最近在出月报数据的时候发现有一个任务节点一直跑不过去,已经超过失败次数的阈值,报警了。 预警很让人头疼,不能上班摸鱼了。 经过分析发现…

多个glibc库存在时如何查看ldd调用的哪个

但是发现存在多个版本的glibc版本,需要查看具体的库的信息,和相应的关键函数的信息,但是并不知道具体的libc.so.6的路径信息 rootalg-dev04:~/xingqiao# ldd --version ldd (GNU libc) 2.29 rootalg-dev04:/opt# which ldd /usr/local/bin/…

工厂自动化升级改造(2)-RS485与Modbus通信协议

在工业控制、电力通信、智能仪表等领域,数据交换通常依赖于串口通信。最初,RS232接口是主流选择,然而,由于工业现场的复杂性,各种电气设备产生的电磁干扰可能导致信号传输错误。 RS232和RS485是两种不同的串行通信协议,它们在电气特性、传输距离和拓扑结构等方面有所不同…

基于springboot的篮球联盟管理系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式 🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 &…

长难句打卡5.8

If it is trying to upset Google, which relies almost wholly on advertising, it has chosen an indirect method: there is no guarantee that DNT by default will become the norm. 如果它想激怒几乎全靠广告业务运营的谷歌公司的话,那么它选择了一个间接的方…

目标检测CNN 目标检测发展历程 应用场景 智慧交通 自动驾驶 工业生产 智慧医疗

目标检测 目标检测是计算机视觉领域中的一个重要任务,其主要目的是让计算机能够自动识别图像或视频帧中所有目标的类别,并在目标周围绘制边界框以标示出每个目标的位置。 目标检测的过程通常包括两个主要步骤:目标定位和目标分类。目标定位是确定图像中是否存在感兴趣的目…

【功耗问题排查】

一、如何处理具体功耗case 在手机功耗测试中,因为我们在功耗测试中(电源电压)为固定值(老手机一般为3.8V左右,现在的大多项目采用4V左右),那么的大小直接由决定,所以,在沟…

在线音视频下载

https://cobalt.tools/ 支持 bilibili 等网站

顺序表的实现(迈入数据结构的大门)(1)

上一节我们认识到了什么是数据结构 这一节我们就来实现第一个数据结构的实现 思考一个问题: 假定一个数组,空间为10,已经使用了5个,向其中插入数据的步骤: 1.插入数据,我们先要求数组长度,其…

做抖音小店怎么选品?这几种实用性选品方式,新手一看就会

大家好,我是电商笨笨熊 做抖音小店,最重要的是选品,最让玩家头疼的还是选品。 选品该怎么选才能选中爆品,怎么做才能让店铺爆单? 笨笨熊做抖店已经四年多的时间,因此也总结出来一套最适合新手玩家去做的…

Stable Diffusion 指定模型,Lora 训练全流程

简介 在使用 Stable Diffusion 的时候,可以选择别人训练好的 Lora,那么如何训练自己的 Lora呢? 本篇文章介绍了如何训练Lora,如何筛选模型,如何在 Stable Diffusion 中使用。 闲话不多说,直接实际操作吧。…

【EI会议|投稿优惠】2024年物理化学与应用数学国际会议(IACPCAM 2024)

2024 International Conference on Physical Chemistry and Applied Mathematics 一、大会信息 会议名称:2024年物理化学与应用数学国际会议会议简称:IACPCAM 2024收录检索:提交Ei Compendex,CPCI,CNKI,Google Scholar等会议官网:…

Debian——安装syzkaller——2024

系统:Debian 远程连接——我是不想安装tools没有办法复制黏贴,所以远程,根据个人情况选择是否远程连接 就是说使用Windows自带的远程mstsc,使用的不是ssh22端口,是TCP 3389端口 mkdir debian cd debian 二:安装go编译器 打开终端。使用wget命令从官方网站或可信的镜像…

SAP-ABAP-视图

1、什么是视图? 当需要查询多个表中的某些字段的数据时,就可以使用视图。视图不影响数据库中的数据,仅作为查询手段或工具。 2、视图类型: 数据库视图和维护视图经常使用。 3、创建视图SE11 3.1、数据库视图 可以直接输入表名…

js实现json数据可编辑

背景 项目中有低代码平台,由于历史脏数据和非同步编辑的问题,偶尔会出现数据错乱的问题,希望有一个快捷的方式修改数据 之前在用Formily的时候有注意到designable/react 里面的json数据编辑功能非常不错如果能应用到项目里就完美了 design…

UE灯光:点光和聚光灯的强度单位(cd、lm)

在虚幻引擎(UE)中,点光和聚光灯的光强使用两种不同的单位进行度量: 坎德拉(cd):坎德拉是光强度的国际单位(SI单位)。它代表光源在特定方向上每单位立体角发出的光通量。…

Chromium编译指南2024 Windows11篇-获取 Chromium 的源代码(五)

前言 在《Chromium编译指南2024(四)》中,我们完成了Git 的初始化配置。 现在,我们将进一步讨论如何获取 Chromium 的源代码,并准备构建所需的文件。 1. 获取Chromium的源代码 在合适的位置准备一个文件夹&#xff…

47. UE5 RPG 实现角色死亡效果

在上一篇文章中,我们实现了敌人受到攻击后会播放受击动画,并且还给角色设置了受击标签。并在角色受击时,在角色身上挂上受击标签,在c里,如果挂载了此标签,速度将降为0 。 受击有了,接下来我们将…