js代碼05

題目

好的,我們進入異步編程的“終極形態”:async/await

async/await 是在 ES2017 (ES8) 中引入的,它并不是一個全新的功能,而是建立在 Promise 之上的語法糖 (Syntactic Sugar)。它的目標是讓我們能夠以一種看似同步、更符合人類直覺的方式來編寫和閱讀異步代碼,從而徹底解決 Promise 鏈條過長的問題。


練習 05: async/await - 像寫同步代碼一樣處理異步

在這個練習中,我們不會去修改上一關寫的 fetchUserData 函數(因為它返回 Promise,已經很完美了)。我們的任務是改變調用它的方式,用 async/await 來替代 .then().catch()

🎯 學習目標:

  • 學會使用 async 關鍵字來聲明一個異步函數。
  • 學會使用 await 關鍵字來“暫停”函數的執行,直到一個 Promise 完成,并獲取其結果。
  • 理解 await 只能在 async 函數內部使用。
  • 學會使用標準的 try...catch 語句來捕獲 await 期間可能發生的錯誤(即 Promise 的 reject)。

背景知識:

  • async function: 在一個函數聲明前加上 async 關鍵字,這個函數就變成了一個異步函數。異步函數有一個重要特性:它總是隱式地返回一個 Promise。如果你的函數代碼返回了一個具體的值(比如一個對象或字符串),async 函數會自動把它包裝在一個 fulfilled 狀態的 Promise 中返回。
  • await operator: await 關鍵字只能用在 async 函數內部。它可以“等待”一個 Promise 對象。當代碼執行到 await somePromise 時,它會暫停當前 async 函數的執行,去處理其他任務。直到 somePromise 完成(無論是 fulfilled 還是 rejected),它才會回來繼續執行。
    • 如果 Promise 成功了,await 會“解包”這個 Promise,并返回成功的值。
    • 如果 Promise 失敗了,await 會拋出一個錯誤,這個錯誤可以被 try...catch 捕獲。

🛠? 任務:

  1. 創建一個名為 processUserData異步函數
  2. processUserData 函數內部,使用 try...catch 結構來處理可能發生的錯誤。
  3. try 代碼塊中:
    • 調用我們之前寫的 fetchUserData(123),并使用 await 關鍵字來獲取成功的結果。
    • 將獲取到的用戶數據打印到控制臺。
  4. catch 代碼塊中:
    • 捕獲可能發生的錯誤,并將其打印到控制臺。
  5. 在主代碼中,調用 processUserData 函數來啟動整個流程。
  6. (可選挑戰) 嘗試在 try 塊中也調用一次 fetchUserData(-1),看看 try...catch 是如何處理錯誤的。

📋 初始代碼:
創建新文件 05-async-await.js。這次你需要從頭開始寫,但可以把上一關的 fetchUserData 函數復制過來,因為我們依然需要它。

// --- 首先,把上一關的 fetchUserData 函數復制到這里 ---
function fetchUserData(userId) {return new Promise((resolve, reject) => {if (userId <= 0) {reject("Invalid User ID");return;}setTimeout(() => {const user = {id: userId,name: 'John Doe',email: 'john.doe@example.com'};resolve(user);}, 2000);});
}// --- 在這里編寫你的新代碼 ---/*** 使用 async/await 來處理獲取用戶數據的流程。*/
async function processUserData() {// 1. 使用 try...catch 來包裹你的異步調用try {// 2. 使用 await 等待 fetchUserData(123) 的結果console.log("正在獲取用戶數據 (userId: 123)...");const user = "在這里使用 await 獲取數據";// 3. 打印成功的結果console.log("成功獲取到用戶:", user);// --- 可選挑戰 ---// console.log("正在嘗試獲取無效用戶 (userId: -1)...");// const invalidUser = await fetchUserData(-1);// console.log("這一行永遠不會被打印");} catch (error) {// 4. 捕獲并打印錯誤console.error("在處理過程中發生錯誤:", error);}
}// --- 最后,調用你的 async 函數來啟動整個流程 ---
console.log("程序開始...");
processUserData();
console.log("程序繼續執行... (async 函數已調用,但內部代碼在等待)");

? 預期輸出:

程序開始...
正在獲取用戶數據 (userId: 123)...
程序繼續執行... (async 函數已調用,但內部代碼在等待)
// ...等待大約2秒...
成功獲取到用戶: { id: 123, name: 'John Doe', email: 'john.doe@example.com' }

如果你嘗試了可選挑戰,輸出會是:

程序開始...
正在獲取用戶數據 (userId: 123)...
程序繼續執行... (async 函數已調用,但內部代碼在等待)
// ...等待大約2秒...
成功獲取到用戶: { id: 123, name: 'John Doe', email: 'john.doe@example.com' }
正在嘗試獲取無效用戶 (userId: -1)...
在處理過程中發生錯誤: Invalid User ID

你會發現,代碼的邏輯流看起來幾乎和同步代碼一模一樣,非常直觀。這就是 async/await 的魔力。

答案

好的,沒問題。勞逸結合是高效學習的關鍵。我們今天就用答案和解析來收尾,明天你再親手實踐,印象會更深刻。

async/await 的美妙之處在于它能讓你把異步代碼寫得像同步代碼一樣,邏輯清晰,易于閱讀。

參考實現 (05-async-await.js)

// --- 首先,把上一關的 fetchUserData 函數復制到這里 ---
function fetchUserData(userId) {return new Promise((resolve, reject) => {// 增加一個錯誤檢查,讓 try...catch 能捕獲到它if (userId <= 0) {reject(`Invalid User ID: ${userId}`);return;}// 模擬2秒的網絡延遲setTimeout(() => {const user = {id: userId,name: 'John Doe',email: 'john.doe@example.com'};// Promise 成功,并返回 user 對象resolve(user);}, 2000);});
}// --- 在這里編寫你的新代碼 ---/*** 使用 async/await 來處理獲取用戶數據的流程。*/
async function processUserData() {console.log("processUserData 函數開始執行...");// 1. 使用標準的 try...catch 語句來包裹可能會出錯的異步代碼try {// 2. 使用 await 等待 fetchUserData(123) 的 Promise 完成//    代碼會在這里“暫停”(非阻塞),直到拿到結果const user = await fetchUserData(123);// 3. 只有在 await 成功后,代碼才會繼續執行到這里console.log("? 成功獲取到用戶:", user);// --- 可選挑戰的實現 ---console.log("---------------------------------");console.log("再次調用,嘗試獲取一個無效用戶...");const invalidUser = await fetchUserData(-1);// 因為上一行會拋出錯誤,所以這一行永遠不會被執行console.log("這一行永遠不會被打印", invalidUser);} catch (error) {// 4. 如果 try 塊中任何一個 await 的 Promise 被 reject,//    代碼會立刻跳轉到 catch 塊中,并將 reject 的原因賦值給 errorconsole.error("? 在處理過程中捕獲到錯誤:", error);}console.log("processUserData 函數執行完畢。");
}// --- 最后,調用你的 async 函數來啟動整個流程 ---
console.log("程序開始...");
processUserData();
console.log("程序繼續執行... (async 函數已調用,但其內部流程在等待)");

代碼解析

  1. async function processUserData()

    • async 關鍵字告訴 JavaScript 引擎:“processUserData 是一個異步函數,它內部可能含有 await,并且這個函數本身會返回一個 Promise。”
  2. const user = await fetchUserData(123);

    • 這是 async/await 的核心。
    • await 做了什么?它告訴 processUserData 函數:“請在這里暫停執行,不要往下走了。去等待 fetchUserData(123) 這個 Promise 的結果。”
    • 如果 Promise 成功 (fulfilled)await 會像拆開禮物包裝一樣,把 Promise 對象里的成功值(也就是 user 對象)取出來,然后把它賦值給左邊的 const user 變量。之后,函數繼續往下執行。
    • 如果 Promise 失敗 (rejected)await 會把 Promise 的失敗原因(我們代碼里的錯誤信息字符串)當作一個錯誤拋出 (throw)
  3. try...catch

    • 這就是 async/await 的優雅之處。因為失敗的 Promise 會被 await 變成一個拋出的錯誤,所以我們可以用最傳統、最熟悉的 try...catch 語句來捕獲它!
    • await fetchUserData(-1) 執行時,Promise 被 rejectawait 拋出錯誤,try 塊的執行立刻中斷,程序流直接跳轉到 catch 塊,并將錯誤信息賦值給 error 變量。

對比 .then/.catch

看一下兩種寫法的直觀對比:

Promise 鏈式寫法:

fetchUserData(123).then(user => {console.log("成功:", user);}).catch(error => {console.error("失敗:", error);});

async/await 寫法:

try {const user = await fetchUserData(123);console.log("成功:", user);
} catch (error) {console.error("失敗:", error);
}

async/await 的版本看起來就像在寫普通的同步代碼,從上到下,非常線性,并且用了我們早已熟悉的 try...catch 來處理錯誤,這大大降低了心智負擔。


好的,今天的內容就到這里。async/await 是目前處理異步操作的社區標準和最佳實踐,掌握它至關重要。

你先好好休息,我們明天再繼續探索 JavaScript 的其他方面!

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

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

相關文章

PyTorch里.pt和.pth的區別

在PyTorch中&#xff0c;.pt和.pth文件均用于保存模型&#xff0c;但兩者在設計初衷、存儲內容和使用場景上存在差異。以下是詳細對比&#xff1a; 1. 核心區別 特性.pt文件.pth文件存儲內容完整模型&#xff08;結構參數優化器狀態等&#xff09;僅模型參數&#xff08;state…

windows電腦如何安裝iis作為部署服務器并

1.控制面板-程序-啟用或關閉windows功能-勾選iis(縮寫) 2.安裝好iis后在開始中搜索iis就可以看見安裝好了的管理器了

解鎖ChatGPT高級玩法:模塊化提示詞庫開發指南

目錄 &#x1f50d; 一、引言&#xff1a;為什么需要模塊化提示詞庫&#xff1f;&#x1f9f1; 二、模塊化提示詞庫設計原理2.1 核心架構2.2 模塊功能說明 ?? 三、模塊化提示詞庫開發實踐&#xff08;附Python源碼&#xff09;3.1 環境配置3.2 模塊化提示詞生成器3.3 提示詞組…

Spring Boot 實現不同用戶不同訪問權限

前提 近期在使用 Spring Boot&#xff0c;用戶角色被分為管理者和普通用戶&#xff1b;角色不同&#xff0c;權限也就存在不同。 在 Spring Boot 里實現不同用戶擁有不同訪問權限&#xff0c;可借助 Spring Security 框架達成。 實現 1. 添加必要依賴 首先要在 pom.xml 里…

華沿協作機器人:數字孿生技術賦能焊接領域智能化升級

在工業4.0與智能制造浪潮的推動下&#xff0c;焊接行業正經歷從傳統工藝向數字化、柔性化轉型的關鍵階段。作為國內協作機器人領域的創新者&#xff0c;華沿機器人通過融合數字孿生、智能感知與多軸協同技術&#xff0c;在焊接場景中實現了技術突破與應用創新。本文將從技術原理…

Linux中部署Nacos保姆級教程

前置說明&#xff1a; Dokcer部署Nacos官方文檔&#xff1a;Nacos Docker 快速開始 | Nacos 官網 一、Nacos版本說明 Nacos 1.x 版本 Nacos 1.1.3 &#xff1a;是一個相對穩定的版本&#xff0c;在一段時期內被廣泛使用&#xff0c;但目前該版本已經下線&#xff0c;不再單獨維…

戰神授權后臺報錯:Parse error: syntax error, unexpected end of file in解決辦法

問題現象分析 當您在戰神授權后臺遇到"Parse error: syntax error, unexpected end of file"這個錯誤時&#xff0c;說明PHP解析器在解析腳本文件時遇到了意外結束的情況。這種錯誤通常發生在PHP代碼結構不完整時&#xff0c;比如缺少閉合的大括號、分號或者PHP結束…

HTML<span>元素詳解

HTML<span>元素詳解 <span> 是 HTML 中最常用的內聯(inline)容器元素&#xff0c;用于對文檔中的部分文本或內容進行標記和樣式化。 一、基本語法 <span>內容</span>二、主要特點 內聯元素&#xff1a;不會獨占一行&#xff0c;只占據內容所需寬度無…

vscode ssh遠程連接到Linux并實現免密碼登錄

vscode ssh遠程連接到Linux并實現免密碼登錄 文章目錄 vscode ssh遠程連接到Linux并實現免密碼登錄一、安裝VSCode擴展二、Linux側工作三、連接四、實現免密登錄 一、安裝VSCode擴展 擴展一欄搜索remote找到Remote Development插件直接點擊Install安裝即可 二、Linux側工作 U…

超級詳細 的 Apache Camel 教程

前言 通過本教程學習 Apache Camel 的基礎知識并在 Spring Boot 項目上創建您的第一個 Camel。 想開始使用Apache Camel嗎&#xff1f;這是我關于這個流行的 Java 集成框架的教程。 我為完整的初學者編寫了這個 Apache Camel 教程。它向您介紹了 Camel 的核心概念&#xff0c;并…

使用GithubActions和騰訊CloudBase自動發布靜態網頁

騰訊 CloudBase 可以用于托管靜態網站&#xff0c;服務開通之后&#xff0c;使用 CloudBase CLI 可以將本地靜態網站上傳到 CloudBase&#xff0c;并生成相應的訪問域名。 配置 Workflow 創建 .github/workflows/deploy.yml 文件, 編輯內容如下&#xff1a; name: Deploy to…

《聊一聊ZXDoc》之汽車標定、臺架標定、三高標定

ZXDoc支持XCP/CCP標定功能&#xff0c;標定工作貫穿主機廠與Tier1廠商汽車ECU研發、生產、測試的整個流程&#xff0c;是保障ECU性能達標、功能穩定的關鍵。 什么是XCP/CCP標定&#xff1f; XCP/CCP標定是汽車電子領域用于ECU標定和測量的核心通信協議&#xff0c;由ASAM組織…

【目標檢測】評估指標詳解:Precision/Recall/F1-Score

&#x1f9d1; 博主簡介&#xff1a;曾任某智慧城市類企業算法總監&#xff0c;目前在美國市場的物流公司從事高級算法工程師一職&#xff0c;深耕人工智能領域&#xff0c;精通python數據挖掘、可視化、機器學習等&#xff0c;發表過AI相關的專利并多次在AI類比賽中獲獎。CSDN…

【unity游戲開發——網絡】網絡協議、TCP vs UDP 本質區別

注意&#xff1a;考慮到熱更新的內容比較多&#xff0c;我將熱更新的內容分開&#xff0c;并全部整合放在【unity游戲開發——網絡】專欄里&#xff0c;感興趣的小伙伴可以前往逐一查看學習。 文章目錄 一、網絡協議概述二、OSI七層模型三、TCP/IP四層模型四、核心傳輸協議對比…

Spark Streaming 與 Flink 實時數據處理方案對比與選型指南

Spark Streaming 與 Flink 實時數據處理方案對比與選型指南 實時數據處理在互聯網、電商、物流、金融等領域均有大量應用&#xff0c;面對海量流式數據&#xff0c;Spark Streaming 和 Flink 成為兩大主流開源引擎。本文基于生產環境需求&#xff0c;從整體架構、編程模型、容…

鴻蒙HarmonyOS 5小游戲實踐:記憶翻牌(附:源代碼)

記憶翻牌游戲是一款經典的益智游戲&#xff0c;它能有效鍛煉玩家的記憶力和觀察能力。本文將詳細介紹如何使用鴻蒙&#xff08;HarmonyOS&#xff09;的ArkUI框架開發一款完整的記憶翻牌游戲&#xff0c;涵蓋游戲設計、核心邏輯實現和界面構建的全過程。 游戲設計概述 記憶翻牌…

【Linux庖丁解牛】— 文件系統!

1 引?"塊"概念 其實硬盤是典型的“塊”設備&#xff0c;操作系統讀取硬盤數據的時候&#xff0c;其實是不會?個個扇區地讀取&#xff0c;這樣 效率太低&#xff0c;?是?次性連續讀取多個扇區&#xff0c;即?次性讀取?個”塊”&#xff08;block&#xff09;。…

如何通過自動化減少重復性工作

通過自動化減少重復性工作的關鍵策略包括&#xff1a;1、識別可被規則化操作的任務、2、引入RPA&#xff08;機器人流程自動化&#xff09;工具、3、整合AI與業務流程系統、4、部署腳本與低代碼平臺、5、持續優化自動化場景與效率。 其中&#xff0c;“引入RPA工具”被廣泛認為…

知識變現全鏈路設計:從IP打造到商業閉環的系統方法論|創客匠人

一、變現低效根源&#xff1a;碎片化努力為何換不來持續增長&#xff1f; 創客匠人服務上千位知識創業者后發現&#xff0c;變現乏力多因缺乏系統設計&#xff1a;某營銷專家的課程因定位模糊、表達生硬、渠道單一&#xff0c;低價仍少有人問。文檔中提出的“六大超級設計公式…

如何利用人工智能大模型提升流量質量

摘要 流量質量是衡量數字化營銷效果的重要指標之一&#xff0c;它反映了用戶對網站或應用的興趣和滿意度。流量質量的常用評估方法有點擊率、跳出率和用戶停留時間等。本文將介紹如何利用人工智能大模型來分析和優化這些指標&#xff0c;提高流量質量&#xff0c;從而提升數字…