深入理解 JavaScript 中的 Promise、async 和 await

深入理解 JavaScript 的 Promise 与 async/await 在 JavaScript 中,异步操作允许程序在等待某个任务完成时,继续执行其他代码,而不会阻塞主线程。这对于处理如网络请求、文件读写、定时器等耗时任务尤为重要。Promise 是一种用于处理异步操作的对象,它代表一个尚未完成但预计会在未来某个时间点完成的操作。Pending(待定) :初始状态,操作尚未完成。Fulfilled(已完成) :操作成功完成。Rejected(已拒绝) :操作失败。在现代 JavaScript 开发中,异步编程至关重要。 阅读详情

序言

在 JavaScript 中,异步编程是一项关键技能。为了更有效地处理异步任务,JavaScript 在其生命周期中引入了一系列功能。其中,Promise、async 和 await 是现代 JavaScript 中最重要的异步编程工具之一。本文将深入探讨这些概念,帮助大家更好地理解它们的作用和用法。

一、回调地狱

回调地狱(callback hell)是指在异步操作中过度嵌套回调函数,导致代码难以阅读和维护的情况。在过去,JavaScript 中处理异步操作通常使用回调函数。回调函数有一些缺点,比如难以管理,导致了回调地狱的问题,代码不易阅读和维护。

// 回调地狱示例中用到的 fetchData 函数的定义
const fetchData = (callback) => {
  setTimeout(() => {
    const success = Math.random() > 0.5; // 模拟操作成功或失败
    if (success) {
      callback('Data fetched successfully');
    } else {
      callback('Failed to fetch data');
    }
  }, Math.random() * 2000); // 模拟不同的执行时间
};

// 示例:回调地狱
fetchData((data) => {
  console.log(data); // 输出第一个异步操作的结果
  fetchData((data) => {
    console.log(data); // 输出第二个异步操作的结果
    fetchData((data) => {
      console.log(data); // 输出第三个异步操作的结果
      // 更多嵌套...
    }, (error) => {
      console.error(error); // 输出可能的错误信息
    });
  }, (error) => {
    console.error(error); // 输出可能的错误信息
  });
}, (error) => {
  console.error(error); // 输出可能的错误信息
});

二、Promise

Promise 是 JavaScript 中处理异步操作的一种强大机制。它允许处理尚未完成的操作,并在操作完成或失败时执行相应的操作。通过 Promise,可以更清晰地表达异步操作的流程,避免了传统的回调地狱问题。

Promise 是一个对象,代表了尚未完成但预计会在未来完成的操作。Promise 可以有三种状态:

  1. Pending(进行中):初始状态,表示操作尚未完成,也没有失败。
  2. Fulfilled(已成功):表示操作已经成功完成。
  3. Rejected(已失败):表示操作失败。

Promise 可以通过 then() 方法来处理成功的结果,通过 catch() 方法来处理失败的结果。这使得异步操作的处理更加清晰和可控。

// 使用 Promise 定义 fetchData 函数
const fetchData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const success = Math.random() > 0.5; // 模拟操作成功或失败
      if (success) {
        resolve('Data fetched successfully');
      } else {
        reject('Failed to fetch data');
      }
    }, Math.random() * 2000); // 模拟不同的执行时间
  });
};

// 示例:使用 Promise 处理异步操作
fetchData()
  .then((data) => {
    console.log(data); // 输出 'Data fetched successfully'
  })
  .catch((error) => {
    console.error(error); // 输出 'Failed to fetch data'
  });

三、Promise 嵌套的 Promise 链

有时候,我们需要依次执行多个异步操作,其中的每个操作依赖于前一个操作的结果。在这种情况下,可以使用 Promise 嵌套的 Promise 链。

// 示例:Promise 嵌套的 Promise 链
const fetchFirstData = () => {
  return new Promise((resolve, reject) => {
    // 模拟异步操作,2秒后返回结果
    setTimeout(() => {
      const success = Math.random() > 0.5; // 模拟操作成功或失败
      if (success) {
        resolve('First data fetched successfully');
      } else {
        reject('Failed to fetch first data');
      }
    }, 2000);
  });
};

const fetchSecondData = () => {
  return new Promise((resolve, reject) => {
    // 模拟异步操作,2秒后返回结果
    setTimeout(() => {
      const success = Math.random() > 0.5; // 模拟操作成功或失败
      if (success) {
        resolve('Second data fetched successfully');
      } else {
        reject('Failed to fetch second data');
      }
    }, 2000);
  });
};

fetchFirstData()
  .then((firstData) => {
    // 输出第一个异步操作的结果
    console.log(firstData); // 输出 'First data fetched successfully'
    // 返回第二个异步操作的 Promise 对象
    return fetchSecondData()
      .then((secondData) => {
        // 输出第二个异步操作的结果
        console.log(secondData); // 输出 'Second data fetched successfully'
      })
      .catch((error) => {
        // 输出第二个异步操作可能的错误信息
        console.error(error); // 输出可能的错误信息
      });
  })
  .catch((error) => {
    // 输出第一个异步操作可能的错误信息
    console.error(error); // 输出可能的错误信息
  });

四、async 和 await

尽管 Promise 解决了回调地狱的问题,但在处理多个异步操作时,可能会导致深层嵌套的 Promise 链,使得代码难以理解。为了解决这个问题,ECMAScript 2017 引入了 async 和 await。它们让异步代码更像同步代码,使得代码更加清晰和易于理解。

// 示例:使用 async 和 await 处理异步操作
const fetchFirstData = () => {
  return new Promise((resolve, reject) => {
    // 模拟异步操作,2秒后返回结果
    setTimeout(() => {
      const success = Math.random() > 0.5; // 模拟操作成功或失败
      if (success) {
        resolve('First data fetched successfully');
      } else {
        reject('Failed to fetch first data');
      }
    }, 2000);
  });
};

const fetchSecondData = () => {
  return new Promise((resolve, reject) => {
    // 模拟异步操作,2秒后返回结果
    setTimeout(() => {
      const success = Math.random() > 0.5; // 模拟操作成功或失败
      if (success) {
        resolve('Second data fetched successfully');
      } else {
        reject('Failed to fetch second data');
      }
    }, 2000);
  });
};

const fetchDataAsync = async () => {
  try {
    // 使用 await 等待第一个异步操作的结果
    const firstData = await fetchFirstData();
    // 输出第一个异步操作的结果
    console.log(firstData); // 输出 'First data fetched successfully'
    
    // 使用 await 等待第二个异步操作的结果
    const secondData = await fetchSecondData();
    // 输出第二个异步操作的结果
    console.log(secondData); // 输出 'Second data fetched successfully'
  } catch (error) {
    // 输出可能的错误信息
    console.error(error);
  }
};

// 调用包含异步操作的函数
fetchDataAsync();

async 和 await 基于 Promise 的语法糖,它们可以让我们以同步的方式编写异步代码,尤其是在处理多个异步操作时,可以极大地提高代码的可读性和可维护性。

五、FAQ

Promise、async 和 await 是 JavaScript 中处理异步编程的核心工具。通过 Promise,可以更灵活地处理异步操作的状态和结果。而 async 和 await 则使异步代码的编写和理解更加直观和简洁。

推荐阅读

  1. 深入探究 Spring Boot Starter:从概念到实践
  2. RBAC 权限设计(五)
  3. Docker Compose:简化多容器应用部署
  4. cURL:命令行下的网络工具
  5. RabbitMQ(Docker 单机部署)
算法思维体操:基于generator生成器自己实现Async/Await(TypeScript) 思路:先使用一个while循环遍历generator生成器收集next次数,然后for循环再遍历generator生成器,前后传递生成器Promise.then得到的值,诀窍是使用setTimeout属于宏队列,promise属于微队列,同一次事件循环中setTimeout总会先于promise执行这一JS异步编程特性。不足之处:generator生成器函数会被执行两次,如果在其中有声明console的话,会让人觉得有些奇怪,但是最终的返回值结果倒是正确。下面是一个Async/Await函数的示例。 阅读详情

相关推荐

优惠券管理

(请设计一个优惠券兑换码生成方案,可以支持20亿以上的唯一兑换码,兑换码长度不超过10,只能包含字母数字,并且要保证生成和校验算法的高效)最后把签名值的后14位、新鲜值(4位)、自增序列(32位)拼接,得到一个50位二进制数,然后与一个较大的质数做异或运算加以混淆,再基于Base32或Base64转码,即可的对兑换码。现在,就剩下防止爆刷了。自增id从1增加到Integer的最大值,可以达到40亿以上个数字,而占用的字节仅仅4个字节,也就是32个bit位,距离50个bit位的限制还有很大的剩余,符合要求!

qq_36312661的博客 2206

异步编程的实现方式以及区别

异步操作以及Promise小笔记

有点打脑壳的博客 729

华硕ROG幻16笔记本电脑模式切换管理工具完美替代华硕奥创中心管理工具

参考文档1这个工具可以完美替代华硕奥创中心工具,可以定制化不同模式下的CPU、GPU、风扇转速、电池计划等。是由华硕开发人员开发的一个纯绿色的系统管理工具。直接展示启动后的工具界面效果图:这个工具也可以一键式停止正在运行的华硕ASUS服务,减少不必要的资源消耗。

追梦&天空的博客 1万+

JavaScript 的 Promise 与 async/await

resolve('操作成功!');} else {reject('操作失败!');});// 操作成功!});

everyStudy的博客 923

洛谷 P5736 【深基7.例2】质数筛

题目描述 输入 n(n\le100)n(n≤100) 个不大于 100000 的整数。要求全部储存在数组中,去除掉不是质数的数字,依次输出剩余的质数。 输入格式 无 输出格式 无 输入输出样例 输入 #1 复制 5 3 4 5 6 7 输出 #1 复制 3 5 7 板子题,使用一下线性筛 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using n

qq_37978559的博客 1117

GD32F303调试小记(一)之USART(接收中断、接收空闲中断+DMA、发送DMA)

前言 之前写了GD32F103调试小记(二)之USART(接收中断、接收空闲中断+DMA、发送DMA)一文。这次我们来看看GD32F303的USART是如何配置的,结合这两篇文章,相信大家GD32的USART配置流程会十分熟悉。 DMA 能大大减轻CPU负荷的东西,建议场景合适的情况下,都去用DMA功能。 USART 一种串行通信协议, ...

欢喜6666的博客 3万+

手把手带你了解:javascript中Promise,async和await的使用

Hello,大家好,今天跟大家聊一下javascript中的Promise,以及aync和await关键字。本篇文章分为三个模块来讲:1、同步和异步;2、Promise;3、async和await。

希望我的分享,能帮助到你 1243

3步搞定专利数据爬取:用Selenium绕过国家知识产权局反爬(附完整代码)

本文详细介绍了3种高效获取专利数据的技术方案,重点解析了使用Selenium绕过国家知识产权局反爬的实战方法,并提供了完整代码示例。文章还探讨了Requests+lxml轻量级方案和混合技术策略,帮助开发者根据需求选择最佳数据爬取方案,特别适合需要专利统计数据的开发者参考。

weixin_29029995的博客 1112

JavaScript 异步编程:Promise 与 async/await 详解

JavaScript 异步编程:Promise 与 async/await 详解

韩旭不会敲代码吧的博客 1066

Orbbec-Gemini-335 深度相机 Python SDK 编译与配置全记录(Windows 环境)

本篇博客将围绕 Windows 系统下 Orbbec SDK 的 Python 配置与编译过程进行详细说明,主要使用的是官方提供的 pyorbbecsdk Python wrapper 项目以及 Orbbec SDK V2 Python Wrapper 配置指南,并记录了安装与配置过程中遇到的若干问题及解决办法。

Junseer的博客 1965

西门子TP900精智系列触摸屏和三菱Q系列PLC以太网通信的组态步骤

西门子TP900精智系列触摸屏和三菱Q系列PLC以太网通信的组态步骤

Robot_PLC_HMI_Automation 6100

js:Promise理解、async和await的理解、宏任务/微任务、异常处理、防抖和节流

Promise理解、async和await的理解(未完成)、构造函数/原型/原型链、防抖和节流、this指向(普通函数,箭头函数,JS/Vue的this)、上下文环境、作用域和闭包

Litt_White的博客 6311

新手必看!一步步教您如何获取可用的D音Cookie(为什么我复制的D音Cookie无法正常使用?)

新手必看!一步步教您如何获取可用的抖音Cookie(为什么我复制的抖音Cookie无法正常使用,无法下载无水印视频?)

XiaoqiangClub的博客 1491

async await 面试题

async function t1() { let a = await "lagou"; console.log(a); } t1(); console.log('a') 先打印A 后执行微任务里的 let a = await “lagou”; console.log(a); 原理其实就是Generator 问题1解析 await是一个表达式,如果后面不是一个 promise 对象,会先把表达式转换成promise function * t1 () { let a = yield "lagou

weixin_45345105的博客 2538

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

深入理解JavaScript中的异步编程:Promise与Async/Await

本文将深入浅出地介绍Promise和Async/Await的概念、用法及其区别,并通过实战案例展示它们的应用。# 深入理解JavaScript中的异步编程:Promise与Async/Await。- **语法上的差异**:Async/Await提供了更简洁的语法,使代码更易读。- **异步编程**:代码的执行不依赖于前一个操作的结果,可以同时处理多个操作。- 但在某些复杂的异步操作中,Promise的链式调用可能更灵活。- 回顾Promise和Async/Await的关键点。

系铃铛 976

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

深入理解JavaScript异步编程:Promise与async/await

本文旨在深入探讨JavaScript中的异步编程概念,重点讲解Promise和async/await的使用及其背后的执行机制。文章首先介绍异步编程的基本概念和挑战,然后详细阐述Promise的工作原理和常见用法。接着,文章深入分析async/await如何简化异步代码的编写和维护。最后,通过实际案例演示如何高效处理异步任务,提高代码的可读性和性能。本文适合希望提升JavaScript编程技能的开发者阅读。

2201_75568026的博客 656

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

用 arduino-esp32 让 ESP32 联网开发只需 30 分钟

arduino-esp32 是乐鑫官方的 ESP32 系列 Arduino 核心,把底层 ESP-IDF 封装成你熟悉的 `setup()/loop()` 写法,内置 WiFi、BLE、I2C、SPI 全套外设库。一块 45 元左右的 DevKitC,加上 30 分钟,就能在这块板子上跑起第一个联网程序。 ## 把环境装好,把灯点亮 推荐走 Arduino IDE 的 Boards Manag

gitblog_00644的博客 67

深入理解 Node.js 中的异步编程:回调函数、Promise 与 async/await

Node.js 是一个基于事件驱动的非阻塞 I/O 模型,这使得它非常适合处理高并发的网络请求。在 Node.js 中,异步编程是一项非常重要的技能。理解和掌握异步编程的不同方式不仅能提高代码的效率,还能让你更好地应对复杂的开发任务。本文将深入探讨 Node.js 中常见的三种异步编程方式:回调函数(Callback)、Promise 和 async/await。通过比较它们的用法和特点,我们能够选择最适合的方式来处理异步任务,并解决其中可能遇到的问题。在编程中,同步和异步同步编程。

一名热衷于技术的全栈开发者,专注于前端与后端的全面技术探索。在这里,我将分享我在技术领域的学习与成长,助力更多开发者的进步。 2163

深入理解异步编程:Node.js中的Promise和Async/Await

本文探讨了Node.js中处理异步操作的两种方式。通过用户注册功能的实例,分析了Promise链可能导致重复重定向的问题,并提出了两个解决方案:一是优化Promise链中的返回值处理,二则推荐使用更简洁的Async/Await语法。文章指出,Async/Await能使异步代码更易读和维护,同时强调了正确处理异步逻辑对应用稳定性的重要性。这些技术能有效提升代码质量和可维护性。

m0_62153576的博客 192

深入理解javascript系列(十九):从Promise开始到async/await

什么是同步与异步的定义,在这里我就不做记录,直接用代码来表示它们之间的区别。首先使用Promise模拟一个发起请求的函数,该函数执行后,会在1s之后返回数值30。function fn() { return new Promise(function(resolve, reject) { setTimeout(function() { resolve(...

weixin_33862993的博客 174

Javascript 知识点

蛋老师 javascript 知识点总结

i_Satan的博客 1834

终极JavaScript测验资源:typeofnan-javascript-quizzes的100+题目分类与学习建议

typeofnan-javascript-quizzes是一个专注于JavaScript测验题目的开源项目,包含100+精心设计的问题及详细解析,适合所有希望提升JavaScript技能的开发者。通过系统的题目分类和针对性练习,你可以快速掌握JavaScript的核心概念与常见陷阱。 ## 📚 项目核心价值:为什么选择这个测验资源? 该项目最大的优势在于其**题目覆盖全面**和**解析专业深

gitblog_00301的博客 284

关于js的9个概念

一,变量赋值(值与引用)        js总是按照值来给变量赋值,当指定的值是js的五种原型类型之一(Boolean、null、undefined、String、Number)时,将为变量分配实际的值,但是,当指定的值是Array、Function或者Object时,将会为变量分配内存对象的引用。 二,闭包  &nb...

weixin_41320468的博客 409
上一篇: 探索生产者/消费者模式:解决并发编程中的资源竞争
下一篇: 【JavaScript】探索 JavaScript 中的解构赋值
知行小栈
博客等级 码龄9年 2506粉丝 153原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值