JavaScript异步编程

回调地狱

        回调地狱是一种由于过度使用嵌套回调函数而导致的代码结构不清晰、难以理解和维护的问题。一个典型例子是嵌套多个回调函数,每个回调函数都作为另一个回调函数的参数。这样会导致各个部分之间高度耦合、程序结构混乱、流程难以追踪,每个任务只能指定一个回调函数,无法使用try catch捕获到回调函数中的异常,不能直接return。

手写Promise

        每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。Promise不仅能够捕获错误,而且也很好地解决了回调地狱的问题。它也存在一些缺点,比如无法取消Promise,错误需要通过回调函数捕获。

const promise = new Promise((resolve, reject) => {resolve('success')reject('err')
})
promise.then(value => {console.log('resolve', value)
}, reason => {console.log('reject', reason)
})
// 输出 resolve success

Promise的三种状态

  • Pending----Promise对象实例创建时候的初始状态
  • Fulfilled----可以理解为成功的状态
  • Rejected----可以理解为失败的状态

状态只能由Pending-->Fulfilled或者Pending-->Rejected,且一但发生改变就不可二次修改。

promise的链式调用

  • 每次调用返回的都是一个新的Promise实例(这就是then可用链式调用的原因)
  • 如果then中返回的是一个结果,会把这个结果传递下一次then中的成功回调
  • 如果then中出现异常,会走下一个then的失败回调
  • 在then中使用了return,那么return的值会被Promise.resolve()包装
  • then中可以不传递参数,如果不传递会透到下一个then中
  • catch会捕获到没有捕获的异常

细数异步场景与处理策略

  • 网络请求:例如使用fetch或XMLHttpRequest进行HTTP请求。

处理策略:使用.then()和.catch()处理Promise,或者使用async/await语法。

  • 定时器:如setTimeout和setInterval。

处理策略:使用回调函数或Promise封装定时器逻辑。

  • 文件读写:如使用FileReader读取文件内容。

处理策略:使用回调函数或Promise封装文件读写逻辑。

  • 事件监听:如点击事件、键盘事件等。

处理策略:在事件处理函数中使用异步代码,但需要注意事件循环和事件队列的处理。

  • Web Workers:用于在后台线程中执行耗时的计算任务,不阻塞主线程。

处理策略:使用postMessage和onmessage进行主线程和Worker线程之间的通信。

  • Promise链:多个异步操作需要依次执行。

处理策略:使用.then()串联多个Promise,或使用async/await语法。

  • 并行处理:多个异步操作可以同时进行,不需要等待其他操作完成。

处理策略:使用Promise.all()等待所有Promise完成,或使用async/await结合Promise.all()。

  • 错误处理:在异步操作中可能会遇到错误,需要妥善处理。

处理策略:使用.catch()捕获Promise中的错误,或使用try/catch捕获async/await中的错误。

从Promise到tj/co

        tj/co是一个基于JavaScript的协程库,它允许以同步的方式编写异步代码。这个库的核心思想是将异步操作转换为可以像同步代码一样顺序执行的流程,从而简化异步编程的复杂性。

        当使用co库时,可以编写一个生成器函数,并在其中使用yield关键字来暂停函数的执行,等待一个Promise的完成。当Promise完成时,生成器函数将恢复执行,并继续执行之后的代码。这个过程看起来就像是同步代码,但实际上它仍然是异步执行的。

const co = require('co');  
function* fetchData() { //生成器函数,使用yield来等待两个网络请求的完成  const user = yield fetch('/users/123').then(response => response.json());  const posts = yield fetch('/posts?user=' + user.id).then(response => response.json());  return posts;  
}  
co(fetchData).then(posts => {  console.log(posts);  
}).catch(err => {  console.error(err);  
});

从callback到promise

        最早期的异步编程主要依赖于回调函数(callback),但这种模式很快就暴露出了诸如回调地狱之类的问题,代码的可读性和维护性变得非常差。为了解决这个问题,Promise被引入作为一种更优雅的方式来处理异步操作。

async与await用法与原理详解

        一个函数如果加上async,那么该函数就会返回一个Promise。

        async关键字用于声明一个函数是异步的。这意味着该函数总是返回一个Promise对象。如果async函数返回一个值,这个值会被Promise对象解析为resolve值;如果async函数抛出异常,这个异常会被Promise对象解析为reject值。

        await关键字只能在async函数内部使用,它会暂停async函数的执行,等待Promise的完成或拒绝,并返回Promise的结果值。正常情况下,await命令后面是一个 Promise对象,返回该对象的结果。如果不是 Promise对象,就直接返回对应的值。

  • async/await只是Promise的语法糖,底层仍是基于Promise实现的,它不能用于普通的回调函数。
  • async/await与Promise一样,是非阻塞的。
  • async/await使得异步代码看起来像同步代码,这正是它的魔力所在。
  • 使用try/catch可以很容易地捕获async函数中的错误,这是处理Promise错误的一种更简洁的方式。
  • 可以在async函数中使用if语句、switch语句和for循环等,根据前一个异步操作的结果来决定是否执行下一个异步操作。

详解Promise A+规范

        Promise A+规范是Promise的官方规范,它详细定义了Promise的行为和特性。这个规范的目标是确保所有的Promise实现都具有一致的行为,从而使得开发者在使用Promise时不必担心不同库或环境之间的差异。

Promise A+规范主要包括以下几个部分:

  • 术语:规范首先定义了一些基本术语,如"promise"、"thenable"、"fulfilled"、"rejected"和"resolution procedure"等。
  • 对象状态:一个Promise对象必须处于以下状态之一:pending(挂起)、fulfilled(实现)或rejected(拒绝)。只有异步操作的结果才能改变这个状态,任何其他操作都无法改变这个状态。
  • then方法:Promise必须提供一个then方法,该方法接受两个参数:onFulfilled和onRejected,它们都是可选的,都是函数。这两个函数都将在promise被相应状态改变后异步执行。then方法返回一个新的promise,这个新的Promise的状态和值取决于onFulfilled或onRejected函数的返回值。
  • Promises/A+规范中的then方法的行为:规范详细描述了then方法的执行过程,包括如何处理onFulfilled和onRejected函数的返回值,如何处理异常,以及如何处理promise链等。

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

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

相关文章

详解顺序结构滑动窗口处理算法

🎀个人主页: https://zhangxiaoshu.blog.csdn.net 📢欢迎大家:关注🔍点赞👍评论📝收藏⭐️,如有错误敬请指正! 💕未来很长,值得我们全力奔赴更美好的生活&…

性能优化问题思考总结

INP 是什么? Interaction to Next Paint (INP) INP是一项指标,通过观察用户在访问网页期间发生的所有点击、点按和键盘互动的延迟时间,评估网页对用户互动的总体响应情况。 互动是指在同一逻辑用户手势期间触发的一组事件处理脚本。例如&a…

龙蜥OS 尝试

> 尝试一下龙蜥OS,和Centos8应该没什么区别。 阿里云版本龙蜥 https://alinux3.oss-cn-hangzhou.aliyuncs.com/aliyun_3_x64_20G_nocloud_alibase_20230727.vhd Index of /anolis/8.8/isos/GA/x86_64/ (openanolis.cn) 网卡 我在虚拟机上安装完后,…

SpringBoot使用classfinal-maven-plugin插件加密Jar包

jar包加密 1、在启动类的pom.xml中加入classfinal-maven-plugin插件 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><…

算法沉淀——动态规划之子数组、子串系列(上)(leetcode真题剖析)

算法沉淀——动态规划之子数组、子串系列 01.最大子数组和02.环形子数组的最大和03.乘积最大子数组04.乘积为正数的最长子数组长度 01.最大子数组和 题目链接&#xff1a;https://leetcode.cn/problems/maximum-subarray/、 给你一个整数数组 nums &#xff0c;请你找出一个具…

计算机设计大赛 深度学习实现行人重识别 - python opencv yolo Reid

文章目录 0 前言1 课题背景2 效果展示3 行人检测4 行人重识别5 其他工具6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习的行人重识别算法研究与实现 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c…

vue3使用elementPlus进行table合并处理

elementPlus中table合并部分列 虚拟数据中公司下有多个客户&#xff0c;公司一样的客户&#xff0c;公司列需要合并&#xff0c;客户如果一样也需要合并进行展示&#xff0c;效果展示 const tableData ref([])自定定义自已想要的数据&#xff0c;一般都是通过接口拿到 //table…

ubuntu+QT+ OpenGL环境搭建和绘图

一&#xff0c;安装OpenGL库 安装OpenGL依赖项&#xff1a;运行sudo apt install libgl1-mesa-glx命令安装OpenGL所需的一些依赖项。 安装OpenGL头文件&#xff1a;运行sudo apt install libgl1-mesa-dev命令来安装OpenGL的头文件。 安装GLUT库&#xff1a;GLUT&#xff08;Ope…

亚马逊巨头都在用的自养号大法,赶快get!

随着时间的推移&#xff0c;越来越多做亚马逊生意的朋友开始意识到自养号的重要性。拥有自养号意味着掌握了一手资源&#xff0c;这种自主性让人感到更安全。高权重的买家号可以享有更多的操作权限&#xff0c;也能获得更好的效果。然而&#xff0c;要想成功地养好自养号并不是…

Netty权威指南——基础篇2(NIO编程)

1 概述 与Socket类和ServerSocket&#xff0c;NIO也提供了SocketChannel和ServerSocketChannel两种不同的套接字通道实现。这两种新增的通道都支持阻塞和非阻塞两种模式。阻塞模式使用简单&#xff0c;但性能和可靠性都不好&#xff0c;非阻塞模式则正好相反。一般来说&#xf…

python Matplotlib Tkinter-->导出pdf报表

环境 python:python-3.12.0-amd64 包: matplotlib 3.8.2 reportlab 4.0.9 import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk import tkinter as tk import tkinter.messagebox as messagebox impor…

46.仿简道云公式函数实战-文本函数-CHAR

1. CHAR函数 函数可将计算机其他类型的数字代码转换为字符。 2. 函数用法 CHAR(number) CHAR 函数可将计算机其他类型的数字代码转换为字符。 Number&#xff1a;用于指定字符的数字。 3. 函数示例 CHAR(10)&#xff0c;即返回值为换行字符"\n"。 目前仿简道…

电脑背景图片怎么设置?这个方法让你一目了然

电脑背景图片的设置是个性化电脑桌面的重要步骤之一。一张美观的背景图片不仅可以为电脑带来视觉愉悦&#xff0c;还能反映个人品味和风格。在本文中&#xff0c;我们将介绍电脑背景图片的设置方法&#xff0c;共包括三种方式&#xff0c;通过分步骤详细说明&#xff0c;帮助用…

解决Maven爆红以及解决 Idea 卡在 Resolving问题

关于 Idea 卡在 Resolving&#xff08;前提是Maven的setting.xml中配置好了阿里云和仓库&#xff09; 参考文章https://blog.csdn.net/jiangyu1013/article/details/95042611 解决Maven爆红参考文章https://devpress.csdn.net/beijing/656d993b76f0791b6eca7bb0.html?dp_toke…

IP 电话

1 IP 电话概述 IP 电话是在互联网上传送多媒体信息。 多个英文同义词&#xff1a; VoIP (Voice over IP) Internet Telephony VON (Voice On the Net) 1.1 狭义的和广义的 IP 电话 狭义的 IP 电话&#xff1a;指在 IP 网络上打电话。 广义的 IP 电话&#xff1a;不仅仅是…

路由器端口映射如何配置?

在网络通信中&#xff0c;路由器是一个重要的设备&#xff0c;它负责将数据包从一个网络传输到另一个网络。路由器的端口映射配置是一种重要的设置&#xff0c;可以使外部网络中的计算机通过访问路由器上的特定端口与内部网络中的计算机进行通信。本文将介绍什么是路由器端口映…

24考研成绩查询时间已公布!附最全查分攻略!

2月26日早上9点起&#xff01; 2024考研初试成绩即将公布&#xff01; 考研初试成绩即将公布&#xff0c;同学们都在紧张地期待着自己的成绩。不同院校的成绩查询入口开通时间有所不同&#xff0c;具体时间请大家查看各自官网的通知。 成绩在哪查&#xff1f;怎么查&#xff1…

【力扣 - 爬楼梯】

题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 方法一&#xff1a;动态规划 思路和算法 我们用 f(x) 表示爬到第 x 级台阶的方案数&#xff0c;考虑最后一步可能跨了一级台阶&#…

LeetCode_Java_转变日期格式、种花问题(题目+思路+代码)

目录 1507. 转变日期格式 605.种花问题 1507. 转变日期格式 给你一个字符串 date &#xff0c;它的格式为 Day Month Year &#xff0c;其中&#xff1a; Day 是集合 {"1st", "2nd", "3rd", "4th", ..., "30th", "3…

Qt篇——QTableWidget保存表格数据到Excel文件中

代码如下&#xff1a; &#xff08;pro文件中添加QT axcontainer&#xff09; #include <QAxObject>void MainWindow::saveTableToExcel() {QDateTime current_date_time QDateTime::currentDateTime();QString excelName "data_" current_date_time.toSt…