当前位置: 首页 > article >正文

【react】在react中async/await一般用来实现什么功能

目录

基本概念

工作原理

优点

注意事项

底层原理

实际应用场景

1. 数据获取 (API 请求)

2. 表单提交

3. 异步状态管理

4. 异步路由切换

5. 异步数据预加载

6. 第三方 API 调用

7. 文件上传/下载

8. 路由导航拦截

关键注意事项


基本概念

async 函数:用 async 关键字声明的函数会返回一个 Promise。如果函数中返回的不是 Promise,JavaScript 会将其包装成一个 resolved 的 Promise

await 关键字:只能用在 async 函数内部,用于等待一个 Promise 的解决结果。如果等待的不是 Promiseawait 会直接返回该值。

示例代码

// 定义一个异步函数
async function fetchData() {try {// 模拟一个异步操作,比如网络请求const response = await fetch('https://api.example.com/data');const data = await response.json(); // 解析响应体为 JSONconsole.log(data);} catch (error) {console.error('Error fetching data:', error);}
}// 调用异步函数
fetchData();

工作原理

async 函数返回一个 Promise

如果函数中返回的是一个普通值,这个值会被包装成一个 resolved 的 Promise

如果函数中返回的是一个 Promise,则直接返回该 Promise

await 暂停函数执行

当遇到 await 时,函数的执行会被暂停,直到等待的 Promise 被解决。

如果等待的不是一个 Promiseawait 会直接返回该值,并继续执行后续代码。

优点

更简洁的代码:相比传统的 Promise 链式调用,async/await 让异步代码看起来像同步代码,逻辑更清晰。

易于调试:错误堆栈更清晰,调试时更容易追踪代码的执行流程。

避免回调地狱:通过 await 逐层等待,避免了嵌套回调的复杂性。

注意事项

只能在 async 函数中使用 await

// 错误:await 不能在普通函数中使用
function normalFunction() {const result = await somePromise(); // 语法错误
}

错误处理

async function fetchData() {try {const response = await fetch('https://api.example.com/data');const data = await response.json();console.log(data);} catch (error) {console.error('Error:', error);}
}

使用 try/catch 块捕获 await 的错误,而不是 .catch()

并发执行: 如果有多个异步操作需要同时执行,可以使用 Promise.all()

async function fetchMultipleData() {const [data1, data2] = await Promise.all([fetch('https://api.example.com/data1').then(res => res.json()),fetch('https://api.example.com/data2').then(res => res.json())]);console.log(data1, data2);
}

底层原理

async/await 的底层是基于 Promise 和事件循环的。当执行一个 async 函数时,函数内部的代码会被包装成一个 Promise,并立即执行。遇到 await 时,当前函数的执行会被暂停,直到等待的 Promise 被解决。解决后,函数会从暂停的地方继续执行。

实际应用场景

1. 数据获取 (API 请求)

从服务器获取数据是最常见的异步操作场景。

import React, { useState, useEffect } from 'react';const DataFetcher = () => {const [data, setData] = useState(null);const [loading, setLoading] = useState(true);const [error, setError] = useState(null);useEffect(() => {const fetchData = async () => {try {const response = await fetch('https://api.example.com/data');if (!response.ok) {throw new Error('Network response was not ok');}const jsonData = await response.json();setData(jsonData);} catch (error) {setError(error.message);} finally {setLoading(false);}};fetchData();}, []);if (loading) return <div>Loading...</div>;if (error) return <div>Error: {error}</div>;return <div>{JSON.stringify(data)}</div>;
};export default DataFetcher;

2. 表单提交

处理表单提交时,使用 async/await 等待服务器响应。

import React, { useState } from 'react';const AsyncForm = () => {const [name, setName] = useState('');const [email, setEmail] = useState('');const [status, setStatus] = useState('idle');const handleSubmit = async (e) => {e.preventDefault();setStatus('submitting');try {const response = await fetch('https://api.example.com/submit', {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({ name, email }),});if (!response.ok) {throw new Error('Failed to submit');}setStatus('success');} catch (error) {setStatus(`Error: ${error.message}`);}};return (<form onSubmit={handleSubmit}><inputtype="text"value={name}onChange={(e) => setName(e.target.value)}placeholder="Name"/><inputtype="email"value={email}onChange={(e) => setEmail(e.target.value)}placeholder="Email"/><button type="submit" disabled={status === 'submitting'}>{status === 'submitting' ? 'Submitting...' : 'Submit'}</button>{status === 'success' && <div>Submitted successfully!</div>}{status.startsWith('Error') && <div>{status}</div>}</form>);
};export default AsyncForm;

3. 异步状态管理

在组件中管理异步状态。

import React, { useState } from 'react';const AsyncStateExample = () => {const [data, setData] = useState(null);const [loading, setLoading] = useState(true);const fetchData = async () => {try {const response = await fetch('https://api.example.com/data');if (!response.ok) {throw new Error('Network response was not ok');}const jsonData = await response.json();setData(jsonData);} catch (error) {console.error('Error fetching data:', error);} finally {setLoading(false);}};return (<div><button onClick={fetchData} disabled={loading}>{loading ? 'Loading...' : 'Fetch Data'}</button>{data && <div>{JSON.stringify(data)}</div>}</div>);
};export default AsyncStateExample;

4. 异步路由切换

在使用 React Router 时,完成异步操作后再切换路由。

import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';const AsyncRouteExample = () => {const [username, setUsername] = useState('');const history = useHistory();const handleLogin = async () => {try {await new Promise((resolve) => setTimeout(resolve, 1000));history.push('/dashboard');} catch (error) {console.error('Login failed:', error);}};return (<div><inputtype="text"value={username}onChange={(e) => setUsername(e.target.value)}placeholder="Username"/><button onClick={handleLogin}>Login</button></div>);
};export default AsyncRouteExample;

5. 异步数据预加载

在组件渲染前预加载数据。

import React, { useState, useEffect } from 'react';const AsyncDataPreload = () => {const [data, setData] = useState(null);const [loading, setLoading] = useState(true);useEffect(() => {const preloadData = async () => {try {const response = await fetch('https://api.example.com/data');if (!response.ok) {throw new Error('Network response was not ok');}const jsonData = await response.json();setData(jsonData);} catch (error) {console.error('Error preloading data:', error);} finally {setLoading(false);}};preloadData();}, []);if (loading) return <div>Loading data...</div>;return <div>{JSON.stringify(data)}</div>;
};export default AsyncDataPreload;

6. 第三方 API 调用

与浏览器 API 或第三方 SDK 交互。

async function getGeolocation() {return new Promise((resolve, reject) => {navigator.geolocation.getCurrentPosition(resolve, reject);});
}function LocationButton() {const [position, setPosition] = useState(null);const handleClick = async () => {try {const pos = await getGeolocation();setPosition({lat: pos.coords.latitude,lng: pos.coords.longitude});} catch (err) {alert('无法获取位置信息');}};return (<div><button onClick={handleClick}>获取当前位置</button>{position && <Map coordinates={position} />}</div>);
}

7. 文件上传/下载

处理文件上传并跟踪进度。

import axios from 'axios';function FileUploader() {const [progress, setProgress] = useState(0);const uploadFile = async (file) => {const formData = new FormData();formData.append('file', file);await axios.post('/api/upload', formData, {onUploadProgress: (e) => {setProgress(Math.round((e.loaded * 100) / e.total));}});};return (<div><input type="file" onChange={e => uploadFile(e.target.files[0])} />{progress > 0 && <ProgressBar value={progress} />}</div>);
}

8. 路由导航拦截

防止用户在有未保存更改时离开页面。

import { useNavigate, useLocation } from 'react-router-dom';function EditArticle() {const [isDirty, setIsDirty] = useState(false);const navigate = useNavigate();useEffect(() => {const unblock = navigate.block((tx) => {if (isDirty && !window.confirm('有未保存的更改,确定离开?')) {tx.retry();}});return () => unblock();}, [isDirty]);const saveArticle = async () => {await fetch('/api/articles', { method: 'PUT' });setIsDirty(false);navigate('/articles');};return (/* 编辑器 UI */);
}

关键注意事项

  1. 组件卸载时的处理useEffect 中使用标志位避免组件卸载后的状态更新。

useEffect(() => {let isMounted = true;const fetchData = async () => {const data = await fetch('/api/data');if (isMounted) setData(data);};fetchData();return () => { isMounted = false; };
}, []);
  1. 错误处理 捕获并处理异步操作中的错误,避免未处理的承诺拒绝。

try {await fetchData();
} catch (error) {if (error.name !== 'AbortError') {showErrorToast(error.message);}
}
  1. 防抖优化 对频繁触发的异步操作使用防抖。

const search = useDebouncedCallback(async (query) => {const results = await fetchResults(query);setResults(results);
}, 500);

通过以上示例和注意事项,可以全面了解在 React 中如何使用 async/await 处理各种异步场景,提升应用的响应性和用户体验。

React 中 async/await 的典型应用场景包括:

  1. 网络请求(GET/POST/PUT/DELETE)

  2. 文件操作(上传/下载)

  3. 浏览器 API 调用(地理位置/摄像头)

  4. 定时任务(延迟执行)

  5. WebSocket 通信

  6. 数据库操作(IndexedDB)

  7. 动画序列控制

  8. 第三方库集成(支付 SDK)

合理使用异步操作可以使:

  • 代码逻辑更清晰(避免回调地狱)

  • 错误处理更直观(try/catch 统一捕获)

  • 用户体验更友好(加载状态/进度提示)

码字不易,各位大佬点点赞呗

相关文章:

【react】在react中async/await一般用来实现什么功能

目录 基本概念 工作原理 优点 注意事项 底层原理 实际应用场景 1. 数据获取 (API 请求) 2. 表单提交 3. 异步状态管理 4. 异步路由切换 5. 异步数据预加载 6. 第三方 API 调用 7. 文件上传/下载 8. 路由导航拦截 关键注意事项 基本概念 async 函数&#xff1a;用…...

Axure项目实战:智慧城市APP(六)市民互动(动态面板、显示与隐藏)

亲爱的小伙伴&#xff0c;在您浏览之前&#xff0c;烦请关注一下&#xff0c;在此深表感谢&#xff01; 课程主题&#xff1a;市民互动 主要内容&#xff1a;动态面板、显示与隐藏交互应用 应用场景&#xff1a;AI产品交互、互动类应用 案例展示&#xff1a; 案例视频&am…...

为何服务器监听异常?

报错&#xff1a; 执行./RCF后出现监听异常--在切换网络后&#xff0c;由于前面没有退出./RCF执行状态&#xff1b;重新连接后&#xff0c;会出现服务器监听异常 原因如下&#xff1a; 由于刚开始登录内网&#xff0c;切换之后再重新登录内网&#xff0c;并且切换网络的过程中…...

1.认识Excel

一 Excel 可以用来做什么 二 提升技巧 1.数据太多 2.计算太累 3.提升数据的价值和意义 4.团队协作 三 学习目标 学习目标不是为了掌握所有的技能&#xff0c;追逐新功能。而是学知识来解决需求&#xff0c;如果之前的技能和新出的技能都可以解决问题&#xff0c;那不学新技能也…...

目标跟踪——deepsort算法详细阐述

deepsort 算法详解 Unmatched Tracks(未匹配的轨迹) 本质角色: 是已存在的轨迹在当前帧中“失联”的状态,即预测位置与检测结果不匹配。 生命周期阶段: 已初始化: 轨迹已存在多帧,可能携带历史信息(如外观特征、运动模型)。 未被观测到: 当前帧中未找到对应的检测框…...

AI Agent 是什么?从 Chatbot 到自动化 Agent(LangChain、AutoGPT、BabyAGI)

1. 引言:AI Agent 的演进 AI Agent(人工智能智能体)是 AI 发展的重要方向之一。早期的 AI 主要以 Chatbot 形式存在,如客服机器人、智能助手等,主要基于 NLP 技术进行任务处理。而随着大模型(LLM)能力的提升,AI Agent 逐步演进为能够自主执行任务的智能体,如 AutoGPT…...

ngx_http_core_root

定义在 src\http\ngx_http_core_module.c static char * ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {ngx_http_core_loc_conf_t *clcf conf;ngx_str_t *value;ngx_int_t alias;ngx_uint_t …...

python康复日记-request库的使用,爬虫自动化测试

一&#xff0c;request的简单应用 #1请求地址 URLhttps://example.com/login #2参数表单 form_data {username: admin,password: secret } #3返回的响应对象response response requests.post(URL,dataform_data,timeout5 ) #4处理返回结果&#xff0c;这里直接打印返回网页的…...

光谱范围与颜色感知的关系

光谱范围与颜色感知是光学、生理学及技术应用交叉的核心课题&#xff0c;两者通过波长分布、人眼响应及技术处理共同决定人类对色彩的认知。以下是其关系的系统解析&#xff1a; ‌1.基础原理&#xff1a;光谱范围与可见光‌ ‌光谱范围定义‌&#xff1a; 电磁波谱中能被特定…...

OpenCV vs MediaPipe:哪种方案更适合实时手势识别?

引言 手势识别是计算机视觉的重要应用&#xff0c;在人机交互&#xff08;HCI&#xff09;、增强现实&#xff08;AR&#xff09;、虚拟现实&#xff08;VR&#xff09;、智能家居控制、游戏等领域有广泛的应用。实现实时手势识别的技术方案主要有基于传统计算机视觉的方法&am…...

el-select下拉框,搜索时,若是匹配后的数据有且只有一条,则当失去焦点时,默认选中该条数据

1、使用指令 当所需功能只能通过直接的 DOM 操作来实现时&#xff0c;才应该使用自定义指令。可使用方法2封装成共用函数&#xff0c;但用指令他人复用时比较便捷。 <el-tablev-loading"tableLoading"border:data"tableList"default-expand-allrow-key…...

网络地址转换技术(2)

NAT的配置方法&#xff1a; &#xff08;一&#xff09;静态NAT的配置方法 进入接口视图配置NAT转换规则 Nat static global 公网地址 inside 私网地址 内网终端PC2&#xff08;192.168.20.2/24&#xff09;与公网路由器AR1的G0/0/1&#xff08;11.22.33.1/24&#xff09;做…...

Python正则表达式(一)

目录 一、正则表达式的基本概念 1、基本概念 2、正则表达式的特殊字符 二、范围符号和量词 1、范围符号 2、匹配汉字 3、量词 三、正则表达式函数 1、使用正则表达式&#xff1a; 2、re.match()函数 3、re.search()函数 4、findall()函数 5、re.finditer()函数 6…...

【TI MSPM0】PWM学习

一、样例展示 #include "ti_msp_dl_config.h"int main(void) {SYSCFG_DL_init();DL_TimerG_startCounter(PWM_0_INST);while (1) {__WFI();} } TimerG0输出一对边缘对齐的PWM信号 TimerG0会输出一对62.5Hz的边缘对齐的PWM信号在PA12和PA13引脚上&#xff0c;PA12被…...

MySQL: 创建两个关联的表,用联表sql创建一个新表

MySQL: 创建两个关联的表 建表思路 USERS 表&#xff1a;包含用户的基本信息&#xff0c;像 ID、NAME、EMAIL 等。v_card 表&#xff1a;存有虚拟卡的相关信息&#xff0c;如 type 和 amount。关联字段&#xff1a;USERS 表的 V_CARD 字段和 v_card 表的 v_card 字段用于建立…...

更改 vscode ! + table 默认生成的 html 初始化模板

vscode ! 快速成的 html 代码默认为&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>D…...

使用LVS的 NAT 模式实现 3 台RS的轮询访问

节点规划 1、配置RS RS的网络配置为NAT模式&#xff0c;三台RS的网关配置为192.168.10.8 1.1配置RS1 1.1.1修改主机名和IP地址 [rootlocalhost ~]# hostnamectl hostname rs1 [rootlocalhost ~]# nmcli c modify ens160 ipv4.method manual ipv4.addresses 192.168.10.7/24…...

R 基础语法

R 基础语法 引言 R 是一种针对统计计算和图形表示而设计的编程语言和环境。它广泛应用于统计学、生物信息学、数据挖掘等领域。本文将为您介绍 R 语言的基础语法,帮助您快速上手。 R 的基本结构 R 语言的基本结构包括:变量、数据类型、运算符、控制结构、函数等。 变量 …...

MySQL实战(尚硅谷)

要求 代码 # 准备数据 CREATE DATABASE IF NOT EXISTS company;USE company;CREATE TABLE IF NOT EXISTS employees(employee_id INT PRIMARY KEY,first_name VARCHAR(50),last_name VARCHAR(50),department_id INT );DESC employees;CREATE TABLE IF NOT EXISTS departments…...

华为p10 plus 鸿蒙2.0降级emui9.1.0.228

需要用到的工具 HiSuite Proxy V3 华为手机助手11.0.0.530_ove或者11.0.0.630_ove应该都可以。 官方的通道已关闭&#xff0c;所以要用代理&#xff0c;127.0.0.1端口7777 https://www.firmfinder.ml/ https://professorjtj.github.io/v2/ https://hisubway.online/articl…...

C# Modbus RTU学习记录

继C# Modbus TCP/IP学习记录后&#xff0c;尝试串口通信。 操作步骤&#xff1a; 1.使用Visual Studio安装Nuget包NModbus.Serial。 2.使用Modbus Slave应用程序&#xff0c;工具栏Connection项&#xff0c;单击Connect&#xff0c;弹窗Connection Setup&#xff0c;修改Con…...

AI+Xmind自动生成测试用例(思维导图格式)

一、操作步骤: 步骤1:创建自动生成测试用例智能体 方式:使用通义千问/豆包智能体生成,以下两个是我已经训练好的智能体,直接打开使用即可 通义智能体: https://lxblog.com/qianwen/share?shareId=b0cd664d-5001-42f0-b494-adc98934aba5&type=agentCard 豆包智能…...

单片机 - 位运算详解(``、`|`、`~`、`^`、`>>`、`<<`)

单片机中的位运算详解&#xff08;&、|、~、^、>>、<<&#xff09; 位运算是单片机编程&#xff08;C/C&#xff09;中经常使用的技巧&#xff0c;用于高效地操作寄存器、I/O 端口和数据。以下是各位运算符的详细解析&#xff0c;并结合单片机实际应用举例。 …...

chrome插件开发之API解析-chrome.tabs.query

chrome.tabs.query 是 Chrome 扩展开发中用于查询浏览器标签页信息的 API。它允许你根据指定的条件获取当前浏览器中所有匹配的标签页。这个 API 返回一个 Promise&#xff0c;解析后会得到一个包含匹配标签页信息的数组。 常见用途 获取当前活动标签页&#xff1a;可以获取当…...

(二)手眼标定——概述+原理+常用方法汇总+代码实战(C++)

一、手眼标定简述 手眼标定的目的&#xff1a;让机械臂和相机关联&#xff0c;相机充当机械臂的”眼睛“&#xff0c;最终实现指哪打哪 相机的使用前提首先需要进行相机标定&#xff0c;可以参考博文&#xff1a;&#xff08;一&#xff09;相机标定——四大坐标系的介绍、对…...

3D点云的深度学习网络分类(按照作用分类)

1. 3D目标检测&#xff08;Object Detection&#xff09; 用于在点云中识别和定位目标&#xff0c;输出3D边界框&#xff08;Bounding Box&#xff09;。 &#x1f539; 方法类别&#xff1a; 单阶段&#xff08;Single-stage&#xff09;&#xff1a;直接预测3D目标位置&am…...

【Linux网络-NAT、代理服务、内网穿透】

一、NAT技术 1.NAT技术背景 之前我们讨论了&#xff0c;IPV4协议中&#xff0c;IP地址数量不充足的问题 NAT技术当前解决IP地址不够用的主要手段&#xff0c;是路由器的一个重要功能 NAT&#xff08;网络地址转换&#xff0c;Network Address Translation&#xff09;是一种…...

Windows 和 Linux 操作系统架构对比以及交叉编译

操作系统与架构兼容性详解 1. 可执行文件格式&#xff1a;PE vs ELF Windows: PE (Portable Executable) 格式 详细解释&#xff1a; PE 格式是 Windows 下的可执行文件标准 包含多个区段&#xff08;Sections&#xff09;&#xff0c;如代码段、数据段、资源段 文件头包含…...

heapq库的使用——python代码

Python中heapq库的基础使用方法和示例代码&#xff0c;包含详细注释说明&#xff1a; 1. 基本功能 heapq 实现的是最小堆&#xff08;父节点值 ≤ 子节点值&#xff09;&#xff0c;核心操作包括&#xff1a; 插入元素&#xff1a;heappush(heap, item)弹出最小值&#xff1a…...

新手村:逻辑回归-理解02:逻辑回归中的伯努利分布

新手村&#xff1a;逻辑回归-理解02&#xff1a;逻辑回归中的伯努利分布 伯努利分布在逻辑回归中的潜在含义及其与后续推导的因果关系 1. 伯努利分布作为逻辑回归的理论基础 ⭐️ 逻辑回归的核心目标是: 建模二分类问题中 目标变量 y y y 的概率分布。 伯努利分布&#xff08…...