【JS】Promise的执行顺序

概述

理解 Promise 的执行顺序时,需要牢记以下两点:

  1. 微任务与宏任务的优先级

    • 微任务:Promise.then()catchfinally 是微任务。
    • 宏任务:setTimeoutsetInterval 是宏任务。
    • 微任务的优先级高于宏任务:在一次事件循环中,先清空所有的微任务队列,再执行下一个宏任务。
  2. Promise 是基于微任务实现的

    • 当一个 Promise 的状态变为 resolvedrejected 时,它的 .then() 回调会被加入微任务队列,等待当前任务(包括微任务)完成后执行。

示例代码分析

代码分析

以下代码可以帮助理解 PromisesetTimeout 的执行顺序:

console.log("script start");setTimeout(() => {console.log("setTimeout 1");
}, 0);Promise.resolve().then(() => {console.log("promise 1");return Promise.resolve().then(() => {console.log("promise 2");});}).then(() => {console.log("promise 3");});setTimeout(() => {console.log("setTimeout 2");
}, 0);console.log("script end");

执行过程解析

  1. 同步任务:立即执行

    • console.log("script start") 输出 "script start".
    • setTimeout 的两个回调函数被放入 宏任务队列,等待事件循环调度。
    • Promise.resolve() 被调用,then() 的回调被放入 微任务队列

    输出结果:

    script start
    script end
    
  2. 主线程执行完同步任务后,开始执行微任务队列

    • 微任务队列的顺序如下:
      • 第一个 .then() 输出 "promise 1" 并返回一个新的 Promise
      • 新的 Promise.then() 输出 "promise 2"
      • 第二个 .then() 输出 "promise 3"

    输出结果:

    promise 1
    promise 2
    promise 3
    
  3. 清空微任务队列后,开始执行宏任务队列

    • 宏任务队列的两个 setTimeout 回调依次执行,输出 "setTimeout 1""setTimeout 2"

    输出结果:

    setTimeout 1
    setTimeout 2
    

最终输出

综合以上,代码的输出顺序为:

script start
script end
promise 1
promise 2
promise 3
setTimeout 1
setTimeout 2

总结

  1. 同步任务优先执行,输出 script startscript end
  2. 微任务队列优先于宏任务队列。
  3. Promise.then() 的回调会依次进入微任务队列。
  4. setTimeout 的回调进入宏任务队列,最后执行。

(拓展)问题补充

如果第一个then不是返回return promise,而是直接执行一个Promise.resolve().then(() => { console.log("promise 2"); });结果是不是
会变成 promise 1promise 3promise 2。结果是的。

为什么会这样?

Promise.resolve().then() 不通过 return 将内部的 Promise 链接到外部 then 时,promise 2 的执行不再是当前链的一部分,它会被单独添加到 微任务队列的末尾,导致执行顺序的变化。


示例代码

以下是修改后的代码:

console.log("script start");Promise.resolve().then(() => {console.log("promise 1");Promise.resolve().then(() => {console.log("promise 2");});}).then(() => {console.log("promise 3");});console.log("script end");

执行过程解析

  1. 同步任务

    • 输出 "script start"
    • 主线程继续,将第一个 Promise.then() 的回调加入 微任务队列
    • 输出 "script end"

    当前输出:

    script start
    script end
    
  2. 微任务队列开始执行

    • 执行第一个 .then(),输出 "promise 1"
      在此回调中,一个新的微任务promise 2 的回调)被加入 微任务队列末尾
    • 执行第二个 .then() 的回调,输出 "promise 3"

    当前输出:

    promise 1
    promise 3
    
  3. 微任务队列剩余任务

    • 微任务队列中剩余的任务是 promise 2 的回调,输出 "promise 2"

    最终输出:

    promise 2
    

总输出结果

综合以上,完整的输出顺序是:

script start
script end
promise 1
promise 3
promise 2

关键点解析

  1. 链式调用和微任务队列
    当你不通过 return 将一个新的 Promise 链接到当前 then,它的回调会独立加入 微任务队列的末尾,而不是成为当前链的一部分。

  2. 对比:返回 Promise
    如果 return Promise.resolve().then(...),那么 promise 2 的执行会成为当前链的一部分,顺序为 promise 1 → promise 2 → promise 3


改变的核心代码

  • 独立的微任务:

    Promise.resolve().then(() => {console.log("promise 2");
    });
    
  • 作为链的一部分:

    return Promise.resolve().then(() => {console.log("promise 2");
    });
    

两种写法的区别在于是否将新的 Promise 加入当前链。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java开发 PDF文件生成方案

业务需求背景 业务端需要能够将考试答卷内容按指定格式呈现并导出为pdf格式进行存档,作为紧急需求插入。导出内容存在样式复杂性,包括特定的字体(中文)、字号、颜色,页面得有页眉、页码,数据需要进行表格聚…

SpringCloud微服务架构

文章目录 认识微服务:SpringCloud 服务拆分及远程调用实现夸远程服务调用使用RestTemplateEureka注册中心 搭建EruekaServer注册服务服务发现 Ribbon负载均衡 修改负载均衡规则解饿加载 Nacos注册中心(nacos一部分功能) 服务注册到nacosnacos…

【设计模式-02】23 种设计模式的分类和功能

在软件工程领域,设计模式是解决常见设计问题的经典方案。1994 年,Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides(四人帮,GoF)在《设计模式:可复用面向对象软件的基础》一书中系统性地总结了…

大模型在自动驾驶领域的应用和存在的问题

大模型在自动驾驶领域的应用与挑战 大模型(如 GPT-4、BERT等)已经在多个领域取得了突破,自动驾驶是其中一个受益颇多的行业。随着人工智能和深度学习的快速发展,自动驾驶技术正在向更加智能化、自动化和安全的方向发展。大模型在…

简历_专业技能_熟悉分布式锁Redisson的原理以及使用

系列博客目录 文章目录 系列博客目录怎么样才能够在简历上写熟悉redisson的应用以及原理1. 清晰描述技能与经验示例: 2. 列举具体应用场景示例项目经验: 3. 展示你对原理的理解示例: 4. 用简历中的关键词突出你的能力示例段落: 5.…

在 IntelliJ IDEA 中开发 GPT 自动补全插件

背景与目标 随着 AI 的发展,GitHub Copilot 等智能代码补全工具在开发者中获得了广泛的应用,极大地提高了编程效率。本篇文章将教你如何开发一个 IntelliJ IDEA 插件,使用 OpenAI 的 GPT API 来实现类似 Copilot 的代码自动补全功能。通过这…

分布式任务调度xxl-job入门案例

XXL-JOB是一个分布式任务调度平台,简单来说就是可以在你指定的时间内调用某个功能,就例如购物某个商品的限时抢购从什么时候开始以及结束抢购类似于这样的。 下面是它的一个仓库地址 http://gitee.com/xuxueli0323/xxl-job 下载之后将项目导入进idea中&…

瑞芯微rk3566刷机流程(黑豹X2)

文章目录 概要 刷机方式 卡刷流程 线刷流程 小结 概要 记录rk3566刷机的过程,纯纯的小白,艰难而有意义的一天。 刷机方式 1、卡刷(tf卡) 2、线刷(双公头usb线) 卡刷流程 1、下载armbian镜像 1、…

MySQL大厂面试题之——事务篇

1、了解事务吗,MySQL中事务的隔离级别有哪些? 读未提交:一个事务还没提交时,它做的变更就能被别的事务看到。读已提交:一个事务提交之后,它做的变更才能被其他事务看到。可重复读:一个事务执行过…

计算机网络——数据链路层-流量控制和可靠传输

一、流量控制 流量控制是指由接收方及时控制发送方发送数据的速率,使接收方来得及接受。 • 停止等待流量控制 • 滑动窗口流量控制 1、停止—等待流量控制 停止-等待流量控制的基本原理是发送方每发出一帧后,就要等待接收方的应答信号&#xff…

计算帐户每月余额,补齐缺失日期:从 SQL 到 SPL

MSSQL 数据库有个资产账户的流水表,日期不连续。 NameDateDebitCreditA2021-01-01100A2021-01-0190A2021-02-01110A2021-03-01050A2021-04-01300B2021-01-01100B2022-02-01012B2022-03-01050B2024-04-0130 现在要统计从期初 2021 年 1 月到期末 2024 年 4 月每个账…

GPT系统重大升级,开创国内先河:o1支持图片识别功能正式上线

文章目录 零、前言一、授权码登录体验优化:一步直达聊天界面二、全新“项目”功能:让工作更有条理三、语音功能升级:全新交互体验四、o1支持图片识别五、总结 零、前言 我是虚竹哥,目标是带十万人玩转ChatGPT。 亲爱的用户&…

RabbitMQ-基本使用

RabbitMQ: One broker to queue them all | RabbitMQ 官方 安装到Docker中 docker run \-e RABBITMQ_DEFAULT_USERrabbit \-e RABBITMQ_DEFAULT_PASSrabbit \-v mq-plugins:/plugins \--name mq \--hostname mq \-p 15672:15672 \-p 5672:5672 \--network mynet\-d \rabbitmq:3…

leetcode 面试经典 150 题:轮转数组

链接轮转数组题序号189题型数组解法1. 额外数组法,2. 原数组翻转法(三次翻转法)难度中等熟练度✅✅✅✅ 题目 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 示例 1: 输入: nums [1,2,…

弹性云服务器ECS“规格”

规格详细资料:规格清单(x86)_弹性云服务器 ECS_华为云 通用计算型 各规格详细介绍请参见通用计算型。 规格名称 计算 磁盘类型 网络 通用计算型X1 CPU/内存配比:自定义vCPU数量范围:1-16处理器:第三…

[读书日志]从零开始学习Chisel 第三篇:Scala面向对象编程——类和对象(敏捷硬件开发语言Chisel与数字系统设计)

3.Scala面向对象编程 3.1类和对象 3.1.1类 类是用class开头的代码定义,定义完成后可以用new类名的方式构造一个对象,对象的类型是这个类。类中定义的var和val类型变量称为字段,用def定义的函数称为方法。字段也称为实例变量,因…

Java SpringBoot使用Apache POI导入导出Excel文件

点击下载《Java SpringBoot使用Apache POI导入导出Excel文件(源代码)》 1. Apache POI 简介 Apache POI 是一个强大的 Java 库,用于处理 Microsoft Office 文档,包括 Excel 文件(.xls 和 .xlsx)。在 Java Spring Boot 项目中&am…

在 macOS 中,设置自动将文件夹排在最前

文章目录 1、第一步访达设置2、第二步排序方式 需要两步设置 1、第一步访达设置 按名称排序的窗口中 2、第二步排序方式 选择名称

汇编环境搭建

学习视频 将MASM所在目录 指定为C盘

Sentinel-5P遥感数据下载及预处理教程【20250105】

Sentinel-5P是欧空局(Europe Space Agency,ESA)于2017年10月13日发射的一颗全球大气污染监测卫星。卫星搭载了对流层观测仪(Tropospheric Monitoring Instrument,TROPOMI),可以有效的观测全球各…