forEach 與 for:非同步對決!
了解循環選擇如何影響非同步效能
在我最近的專案中,我需要更新 NoSQL 資料庫中的大量記錄—超過一千筆。由於一次性更新它們是不可行的,而且該過程也是非同步的,因此我決定以較小的批次(每批 20 條記錄)處理它們。我使用 forEach 在循環中實現了這一點,其中每組 20 個將在進入下一組之前更新。然而,在將這種方法付諸實踐後,我注意到並非所有記錄都按預期更新,即使在這些較小的批次中也是如此。例如,當我嘗試更新一批 25 筆記錄時,只有 10 筆記錄成功更新。其他10筆記錄沒有日誌,更新失敗的記錄數量隨機變化-有時12條,有時5條,有時7條。
經過進一步調試,我發現這些記錄很可能在更新過程中被跳過。現在,為什麼會發生這種情況?讓我們探討這個問題,以了解該行為並確定背後的潛在原因。
問題
經過一些研究,我發現在 forEach 循環中使用非同步函數而沒有適當的機制來等待所有迭代可能會導致問題。在這種情況下,我們在 forEach 循環中使用了 async/await,但沒有確保等待所有迭代(請參閱下面的程式碼):
async function patchRecords(records) { // Here, the length of records is 25 let successfulUpdates = 0; // Initialize a counter for successful updates records.forEach(async (item) => { await databaseName.patch(item); successfulUpdates++; // Increment counter on successful update }); // Return the number of records updated successfully return successfulUpdates; } const response = await patchRecords(records); // Make sure to await this call
在上面的程式碼中,沒有任何機制可以確保循環的所有非同步迭代都完成。 forEach 方法會觸發多個非同步呼叫來修補記錄,但 patchRecords 函數很快到達回傳語句,而無需等待這些修補完成。因此,當更新在背景處理時,功能會繼續執行,而無需等待更新完成。這可能會導致一些待處理的承諾仍未兌現,從而可能導致跳過或丟棄更新。
解
那我們該如何解決這個問題呢?在我們開始討論解決方案之前,我們首先了解迭代資料的不同方法。從根本上來說,有兩種方法:順序迭代資料或並行。
如果您想以順序方式非同步迭代數據,使用 forEach 循環可能會導致我們討論的問題。相反,最好使用現代的for…of 循環或簡單的for 循環,因為它們允許await 正常工作並確保所有更新都不會處理被跳過(請參閱下面的程式碼)。
async function patchRecords(records) { // Here, the length of records is 25 let successfulUpdates = 0; // Initialize a counter for successful updates records.forEach(async (item) => { await databaseName.patch(item); successfulUpdates++; // Increment counter on successful update }); // Return the number of records updated successfully return successfulUpdates; } const response = await patchRecords(records); // Make sure to await this call
另一方面,如果你想並行處理記錄,再次使用 forEach 將無法運作。雖然每個非同步回調確實會傳回一個承諾,但其中一些承諾可能仍然未實現,因為它們沒有被等待。相反,使用 map 產生 Promise 數組,然後使用 Promise.all 等待它們(請參閱下面的程式碼)。
async function patchRecords(records) { let successfulUpdates = 0; // Counter for successful updates for (const item of records) { try { // Query to patch each record await databaseName.patch(item); successfulUpdates++; // Increment counter on success } catch { // Handle any errors } } return successfulUpdates; // Return the number of records updated successfully } const response = await patchRecords(records); // Make sure to await this call
這顯示了選擇正確的循環方法如何極大地影響非同步操作的預期結果。您使用的循環類型 - 無論是 forEach、for...of 或標準 for 循環 - 對於程式碼管理非同步任務的效果起著至關重要的作用。
總結
- 挑戰:使用forEach批次更新記錄導致更新不一致,許多記錄被跳過。
- 根本原因: forEach 不等待非同步操作完成,導致未實現的承諾。
- 解決方案: 使用 for…of 循環順序等待每個記錄更新以確保準確性,或使用 Map 和 Promise.all 進行並發更新。
我解釋清楚了嗎?請在下面的評論中告訴我。
我很高興分享我的經驗,希望你也覺得它很有價值!由於我仍在探索這個領域,我希望得到您的回饋和建議。 ☺️ 如果您發現我可以改進的地方,或者有您希望我涵蓋的主題,請隨時與我們聯繫! ?網站。我很高興能在您的幫助下學習和成長。 ??
以上是forEach 與 for:非同步對決!的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。
