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