掌握JavaScript異步操作:Async/Await詳解
本文深入探討JavaScript中的async
/await
,教你如何高效掌控異步操作,編寫更清晰易讀的代碼。
核心要點:
async
/await
簡化了異步操作的處理,使代碼看起來像同步執行,但實際上仍然是非阻塞的。 async
函數返回一個Promise,await
關鍵字暫停函數執行,直到Promise解決,從而增強代碼的可讀性和流程控制。 async
函數的錯誤處理可以使用try
/catch
塊或Promise
的catch()
方法高效管理。 Promise.all
可以優化並行運行異步命令,允許多個Promise
同時解決,而不是順序執行。 for...of
循環允許在循環中正確處理async
函數,確保正確的執行順序和更好的性能管理。 await
允許在ES模塊的頂層使用await
,簡化了異步代碼的集成,無需額外的包裝器。 內容概要:
async
關鍵字await
關鍵字await
/async
底層使用Promiseasync
/await
catch()
方法await
await
在JavaScript中,一些操作是異步的。這意味著它們產生的結果或值不會立即可用。
考慮以下代碼:
function fetchDataFromApi() { // 数据获取逻辑 console.log(data); } fetchDataFromApi(); console.log('数据获取完成');
JavaScript解釋器不會等待異步fetchDataFromApi
函數完成,然後才執行下一條語句。因此,它會在記錄API返回的實際數據之前記錄数据获取完成
。
在許多情況下,這不是預期的行為。幸運的是,我們可以使用async
和await
關鍵字來使我們的程序等待異步操作完成,然後再繼續執行。
此功能在ES2017中引入JavaScript,並受所有現代瀏覽器支持。
如何創建JavaScript異步函數
讓我們仔細看看fetchDataFromApi
函數中的數據獲取邏輯。 JavaScript中的數據獲取是異步操作的一個主要示例。
使用Fetch API,我們可以這樣做:
function fetchDataFromApi() { // 数据获取逻辑 console.log(data); } fetchDataFromApi(); console.log('数据获取完成');
這裡,我們從JokeAPI獲取一個編程笑話。 API的響應採用JSON格式,因此在請求完成後(使用json()
方法)我們提取該響應,然後將笑話記錄到控制台。
請注意,JokeAPI是一個第三方API,因此我們無法保證返回的笑話質量!
如果我們在瀏覽器或Node(使用--experimental-fetch
標誌的17.5 版本)中運行此代碼,我們會看到控制台仍然以錯誤的順序記錄內容。
讓我們改變一下。
async
關鍵字我們需要做的第一件事是將包含函數標記為異步函數。我們可以使用async
關鍵字來實現這一點,我們將它放在function
關鍵字的前面:
function fetchDataFromApi() { fetch('https://v2.jokeapi.dev/joke/Programming?type=single') .then(res => res.json()) .then(json => console.log(json.joke)); } fetchDataFromApi(); console.log('数据获取完成');
異步函數始終返回一個Promise(稍後詳細介紹),因此只需將then()
鏈接到函數調用即可獲得正確的執行順序:
async function fetchDataFromApi() { fetch('https://v2.jokeapi.dev/joke/Programming?type=single') .then(res => res.json()) .then(json => console.log(json.joke)); }
如果我們現在運行代碼,我們會看到類似這樣的內容:
fetchDataFromApi() .then(() => { console.log('数据获取完成'); });
但我們不想這樣做! JavaScript的Promise語法可能會有點複雜,這就是async
/await
閃光的地方:它使我們能夠使用看起來更像同步代碼的語法來編寫異步代碼,並且更易於閱讀。
await
關鍵字接下來要做的是在函數中任何異步操作的前面加上await
關鍵字。這將強制JavaScript解釋器“暫停”執行並等待結果。我們可以將這些操作的結果分配給變量:
<code>程序员的浪漫:一行代码解决千行代码的bug。 数据获取完成</code>
我們還需要等待調用fetchDataFromApi
函數的結果:
async function fetchDataFromApi() { const res = await fetch('https://v2.jokeapi.dev/joke/Programming?type=single'); const json = await res.json(); console.log(json.joke); }
不幸的是,如果我們現在嘗試運行代碼,我們會遇到一個錯誤:
await fetchDataFromApi(); console.log('数据获取完成');
這是因為我們不能在非模塊腳本的async
函數之外使用await
。我們稍後將更詳細地介紹這一點,但現在解決這個問題最簡單的方法是用它自己的函數包裝調用代碼,我們也將其標記為async
:
<code>Uncaught SyntaxError: await is only valid in async functions, async generators and modules</code>
如果我們現在運行代碼,所有內容都應該按正確的順序輸出:
async function fetchDataFromApi() { const res = await fetch('https://v2.jokeapi.dev/joke/Programming?type=single'); const json = await res.json(); console.log(json.joke); } async function init() { await fetchDataFromApi(); console.log('数据获取完成'); } init();
我們需要這個額外的樣板代碼這一事實是不幸的,但在我看來,代碼仍然比基於Promise的版本更容易閱讀。
前面的示例使用了兩個命名函數聲明(function
關鍵字後跟函數名),但我們並不局限於此。我們還可以將函數表達式、箭頭函數和匿名函數標記為async
。
如果您想回顧一下函數聲明和函數表達式之間的區別,請查看我們的指南
(後續內容同理,根據原文逐段改寫,保持原意,並調整語言風格,使之更流暢自然)
以上是初學者的JavaScript異步指南,等待示例的詳細內容。更多資訊請關注PHP中文網其他相關文章!