摘要:譯數(shù)組循環(huán)的幾個坑原文地址原文作者在循環(huán)中使用循環(huán)遍歷數(shù)組似乎很簡單,但是在將兩者結(jié)合使用時需要注意一些非直觀的行為。循環(huán)的情況問題如上述代碼能夠正常執(zhí)行。但我還是喜歡循環(huán)帶來的簡潔和高可讀性。
[譯]async-await 數(shù)組循環(huán)的幾個坑
原文地址:https://medium.com/dailyjs/th...
原文作者:Tory Walker
在 Javascript 循環(huán)中使用 async/ await 循環(huán)遍歷數(shù)組似乎很簡單,但是在將兩者結(jié)合使用時需要注意一些非直觀的行為。讓我們看看三個不同的例子,看看你應(yīng)該注意什么,以及哪個循環(huán)最適合特定用例。
forEach 循環(huán)的情況const urls = [ "https://jsonplaceholder.typicode.com/todos/1", "https://jsonplaceholder.typicode.com/todos/2", "https://jsonplaceholder.typicode.com/todos/3" ]; async function getTodos() { await urls.forEach(async (url, idx) => { const todo = await fetch(url); console.log(`Received Todo ${idx+1}:`, todo); }); console.log("Finished!"); } getTodos();
Finished! Received Todo 2, Response: { ··· } Received Todo 1, Response: { ··· } Received Todo 3, Response: { ··· }
??問題 1:
如上述代碼能夠正常執(zhí)行。但是注意 Finished! 消息,被率先打印了。盡管我們使用了 await 但他仍然不會等待所有 await 執(zhí)行完畢
?? 問題 2:
然而,盡管 await 在循環(huán)中使用,但它并沒有等待每個請求在執(zhí)行下一個請求之前完成。請求不會按照順序一步一步被發(fā)送出去。如果第一個請求的時間比以下請求的時間長,它仍然可以在最后完成。
因此,根據(jù)上述原因,forEach 在和 async/await 搭配使用的時候并不是一個靠得住的東西
Promise.all 方法我們首先需要解決的就是等待所有循環(huán)執(zhí)行完畢。await 操作符返回一個 promise,我們可以使用 Promise.all 方法去并行執(zhí)行所有的請求。最后去 await 所有 promise 返回的結(jié)果
const urls = [ "https://jsonplaceholder.typicode.com/todos/1", "https://jsonplaceholder.typicode.com/todos/2", "https://jsonplaceholder.typicode.com/todos/3" ]; async function getTodos() { const promises = urls.map(async (url, idx) => console.log(`Received Todo ${idx+1}:`, await fetch(url)) ); await Promise.all(promises); console.log("Finished!"); } getTodos();
Received Todo 1, Response: { ··· } Received Todo 2, Response: { ··· } Received Todo 3, Response: { ··· } Finished!
我們解決了不等待所有請求執(zhí)行完畢后打印 Finished!,看起來我們似乎也解決了請求順序的問題。
實際上,上文中已經(jīng)提到過,Promise.all 方法會按照并行的模式,將所有請求一次性全部發(fā)送出去,然后等待接收到全部結(jié)果后,按照順序打印出來而已。它并不會按照順序發(fā)送一個請求,收到結(jié)果后再發(fā)送下一個請求。
這非常適合不需要按照順序發(fā)送的情況,但如果你想要的是串行發(fā)送請求那么 Promise.all 并不適合
for-of 循環(huán)以上的兩種方法并不能完美解決那兩個問題。
for-of 循環(huán)則能夠按照預(yù)期順序執(zhí)行——等待上一個 await 執(zhí)行完畢后,再接著下一個。
const urls = [ "https://jsonplaceholder.typicode.com/todos/1", "https://jsonplaceholder.typicode.com/todos/2", "https://jsonplaceholder.typicode.com/todos/3" ]; async function getTodos() { for (const [idx, url] of urls.entries()) { const todo = await fetch(url); console.log(`Received Todo ${idx+1}:`, todo); } console.log("Finished!"); } getTodos();
Received Todo 1, Response: { ··· } Received Todo 2, Response: { ··· } Received Todo 3, Response: { ··· } Finished!
我特別喜歡這種使代碼保持線性的方法,這是使用 async/await 的關(guān)鍵優(yōu)勢之一。我覺得它比其他選擇更容易閱讀。
如果您不需要訪問索引,則代碼變得更加簡潔:
for(ur url of urls){···}
使用for...of循環(huán)的一個主要缺點是它與Javascript中的其他循環(huán)選項相比性能不夠好。但是,將性能參數(shù)用于await異步調(diào)用時,性能參數(shù)可以忽略不計,因為目的是在每個調(diào)用解析之前保持循環(huán)。我通常只使用for...of進行異步。
當(dāng)然你也可以使用 for 循環(huán)得到 for-of 循環(huán)所有好處。但我還是喜歡 for-of 循環(huán)帶來的簡潔和高可讀性。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/109032.html
摘要:有兩個陌生的關(guān)鍵字,同時函數(shù)執(zhí)行結(jié)果似乎返回了一個對象。用來表示函數(shù)是異步的,定義的函數(shù)會返回一個對象,可以使用方法添加回調(diào)函數(shù)。如果的是對象會造成異步函數(shù)停止執(zhí)行并且等待的解決如果等的是正常的表達式則立即執(zhí)行。 視頻講解 關(guān)于異步處理,ES5的回調(diào)使我們陷入地獄,ES6的Promise使我們脫離魔障,終于、ES7的async-await帶我們走向光明。今天就來學(xué)習(xí)一下 async-a...
摘要:在前端開發(fā)中,經(jīng)常要用去拿后臺接口返回的數(shù)據(jù),總結(jié)幾個的回調(diào)的常見問題,供大家參考爬坑。未定義,可能會造成的傳入后臺的數(shù)據(jù)亂碼,可以加上如下代碼在請求中約定好傳到后臺以及后臺返回的數(shù)據(jù)類型,一般定義類型。 在前端開發(fā)中,經(jīng)常要用ajax去拿后臺接口返回的數(shù)據(jù),總結(jié)幾個ajax的回調(diào)的常見問題,供大家參考爬坑。 未定義contentType,可能會造成的傳入后臺的數(shù)據(jù)亂碼,可以加上如下...
摘要:在前端開發(fā)中,經(jīng)常要用去拿后臺接口返回的數(shù)據(jù),總結(jié)幾個的回調(diào)的常見問題,供大家參考爬坑。未定義,可能會造成的傳入后臺的數(shù)據(jù)亂碼,可以加上如下代碼在請求中約定好傳到后臺以及后臺返回的數(shù)據(jù)類型,一般定義類型。 在前端開發(fā)中,經(jīng)常要用ajax去拿后臺接口返回的數(shù)據(jù),總結(jié)幾個ajax的回調(diào)的常見問題,供大家參考爬坑。 未定義contentType,可能會造成的傳入后臺的數(shù)據(jù)亂碼,可以加上如下...
閱讀 2676·2021-11-25 09:43
閱讀 2484·2021-09-22 15:29
閱讀 1000·2021-09-22 15:17
閱讀 3640·2021-09-03 10:36
閱讀 2236·2019-08-30 13:54
閱讀 1757·2019-08-30 11:23
閱讀 1171·2019-08-29 16:58
閱讀 1301·2019-08-29 16:14