JavaScript中的异步编程

news/2025/1/22 8:30:40/

当我们在编写JavaScript代码时,经常会遇到需要执行长时间运行的任务的情况,例如从服务器获取数据或进行复杂的计算。在这些情况下,我们不希望阻塞用户界面,因为这会使网站看起来卡顿,甚至无响应。为了避免这种情况,我们需要使用JavaScript中的异步编程技术。

异步编程是JavaScript中的一个核心概念,它使我们能够在执行长时间运行的任务时不会阻塞用户界面,而是在任务完成后立即返回结果。本文将介绍JavaScript中的异步编程方式,并探讨它们的优缺点,以及如何使用它们来解决常见的异步编程问题。

一、回调函数

回调函数是JavaScript中最早和最基本的异步编程方式。它通过在函数参数中传递一个函数,让我们能够在异步操作完成后调用该函数。例如,我们可以使用XMLHttpRequest对象从服务器获取数据:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://example.com/data');
xhr.onreadystatechange = function() {if (xhr.readyState === 4 && xhr.status === 200) {console.log(xhr.responseText);}
};
xhr.send();

在上面的例子中,我们定义了一个XMLHttpRequest对象,然后使用open()方法设置请求的类型和URL。然后,我们为onreadystatechange属性指定了一个函数,当readyState属性变为4且状态码为200时,该函数将被调用。在该函数中,我们可以访问响应文本并在控制台中打印它。

虽然回调函数是JavaScript中最早和最基本的异步编程方式,但它有一些缺点。首先,如果我们需要进行嵌套异步操作,回调函数将变得非常复杂和难以理解。其次,回调函数容易出现回调地狱问题,这是指代码中有太多的回调函数,使得代码难以维护和扩展。

二、Promise

为了解决回调地狱问题,JavaScript引入了Promise,它是一种更加高级的异步编程方式。Promise通过将异步操作的结果封装在一个对象中,使得我们可以更加清晰和简洁地处理异步操作。例如,我们可以使用Promise从服务器获取数据:

fetch('https://example.com/data').then(response => response.text()).then(text => console.log(text)).catch(error => console.error(error));

在上面的例子中,我们使用fetch()方法发起一个HTTP请求,并将其封装在一个Promise对象中。然后,我们使用.then()方法指定一个函数,当Promise对象的状态变为fulfilled时将被调用。在这个函数中,我们可以访问响应对象并将其转换为文本。然后,我们使用.then()方法指定另一个函数,当上一个Promise对象的状态变为fulfilled时将被调用。在这个函数中,我们可以访问响应文本并在控制台中打印它。最后,我们使用.catch()方法指定一个函数,当Promise对象的状态变为rejected时将被调用。在这个函数中,我们可以处理错误。

Promise还提供了一些其他的方法,如Promise.all()和Promise.race()。Promise.all()可以同时处理多个Promise对象,并在所有Promise对象都变为fulfilled时返回一个包含所有结果的数组。例如:

Promise.all([fetch('https://example.com/data1'),fetch('https://example.com/data2')
]).then(responses => Promise.all(responses.map(response => response.text()))).then(texts => console.log(texts)).catch(error => console.error(error));

在上面的例子中,我们使用Promise.all()方法同时发起两个HTTP请求,并将它们封装在一个数组中。然后,我们使用.then()方法指定一个函数,该函数将结果数组作为参数,并使用Promise.all()方法将结果数组中的所有响应对象转换为文本。最后,我们使用.then()方法指定另一个函数,该函数将文本数组作为参数并在控制台中打印它们。

Promise.race()可以处理多个Promise对象,并在第一个Promise对象变为fulfilled或rejected时返回它的结果。例如:

Promise.race([new Promise(resolve => setTimeout(() => resolve('foo'), 2000)),new Promise((resolve, reject) => setTimeout(() => reject(new Error('bar')), 1000))
]).then(result => console.log(result)).catch(error => console.error(error));

在上面的例子中,我们使用Promise.race()方法处理两个Promise对象,其中一个会在2秒后返回字符串'foo',另一个会在1秒后返回一个错误对象。由于第二个Promise对象先返回结果,所以Promise.race()返回错误对象并在.catch()方法中处理它。

三、async/await

async/await是ES2017中引入的一种异步编程方式,它建立在Promise之上,并提供了更加简洁和直观的语法。async/await使用async函数来表示异步操作,并使用await关键字来等待Promise对象的完成。例如,我们可以使用async/await从服务器获取数据:

async function getData() {try {const response = await fetch('https://example.com/data');const text = await response.text();console.log(text);} catch (error) {console.error(error);}
}
getData();

在上面的例子中,我们定义了一个async函数getData(),并在其中使用await关键字等待fetch()方法返回一个响应对象。然后,我们再次使用await关键字等待将响应对象转换为文本。最后,我们可以在控制台中打印文本或处理错误。

与Promise一样,async/await也支持多个异步操作的处理。例如,我们可以使用Promise.all()和async/await同时处理多个Promise对象:

async function getData() {try {const responses = await Promise.all([fetch('https://example.com/data1'),fetch('https://example.com/data2')]);const texts = await Promise.all(responses.map(response => response.text()));console.log(texts);} catch (error) {console.error(error);}
}
getData();


在上面的例子中,我们定义了一个async函数getData(),并在其中使用Promise.all()方法同时发起两个HTTP请求并等待它们完成。然后,我们使用await关键字等待将响应对象转换为文本,并将所有结果放入一个数组中。最后,我们可以在控制台中打印文本数组或处理错误。

总结

JavaScript是一门强大的编程语言,具有异步编程的优势。在本文中,我们介绍了三种常见的异步编程方式:回调函数、Promise和async/await。回调函数是异步编程的基础,但它的嵌套结构和错误处理使得代码难以维护。Promise是回调函数的一种改进,它通过链式调用和错误处理提供了更好的可读性和可维护性。最后,async/await建立在Promise之上,提供了更加简洁和直观的语法。当我们需要处理多个异步操作时,Promise.all()和Promise.race()提供了一种有效的方法。无论是哪种方式,我们都可以在JavaScript中使用异步编程来实现更好的性能和用户体验。
 


http://www.ppmy.cn/news/56948.html

相关文章

【五一创作】【笔记】Git|如何将仓库中所有的 commit 合成一个?又名,如何清除所有 git 提交记录?(附 git rebase 机制的简要分析)

在对代码进行开源时,我们往往并不希望代码开发过程中的提交记录被其他人看到,因为提交的过程中往往会涵盖一些敏感信息。因此会存在 将仓库中所有 commit 合成一个 的需求。 直觉上,往往会用 rebase 和 squash 或 reset,不过我尝…

文件上传下载系列——如何实现文件秒传

文章目录 🎃简介: 👻核心思想: MD5是什么? 实现步骤: 🎄实操: 1、java生成文件MD5码 2、javascript生成文件MD5码 ⛳️基于秒传的分片上传下载 上传: 下载&…

交叉熵损失函数原理详解

交叉熵损失函数原理详解 在学习pytorch的神经网络模型里,经常用到交叉熵损失函数(CrossEntropy Loss),只知道它是分类问题中经常使用的一种损失函数,对于其内部的原理总是模模糊糊,而且一般使用交叉熵作为损失函数时,…

【Python】操作MySQL

一、Python 操作 Mysql的方式 Python 操作 Mysql 主要包含下面 3 种方式: Python-MySql Python-MySql 由 C 语法打造,接口精炼,性能最棒;但是由于环境依赖多,安装复杂,已停止更新,仅支持 Python…

密码学【java语言】初探究

文章目录 前言一 密码学1.1 古典密码学1.1.1 替换法1.1.2 移位法1.1.3 古典密码破解方式 二 近代密码学2.1 现代密码学2.1.1 散列函数2.1.2 对称密码2.1.3 非对称密码 二 凯撒加密的实践2.1 基础知识:ASCII编码2.2 ascii编码演示2.3 凯撒加密和解密实践2.4 频率分析…

多项式加法(用 C 语言实现)

目录 一、多项式的初始化 二、多项式的创建 三、多项式的加法 四、多项式的输出 五、清除链表 六、主函数 用链表实现多项式时,每个链表节点存储多项式中的一个非零项,包括系数(coef)和指数(exp)两个…

权限提升:漏洞探针.(Linux系统)

权限提升:漏洞探针. 权限提升简称提权,由于操作系统都是多用户操作系统,用户之间都有权限控制,比如通过 Web 漏洞拿到的是 Web 进程的权限,往往 Web 服务都是以一个权限很低的账号启动的,因此通过 Webshel…

python-使用Qchart总结3-绘制曲线图

1.将画好的图表关联 解释说明图 2.新建一个文件画曲线图,并关联到UI的py文件上,上代码 import sys from PyQt5.Qt import * from PyQt5.QtChart import QChartView, QChart, QValueAxis, QSplineSeries from PyQt5.QtGui import QPainter, QColor, QFon…