當前位置:編程學習大全網 - 編程語言 - JS 的異步遍歷,妳真的會寫嗎?

JS 的異步遍歷,妳真的會寫嗎?

我們有時候需要遍歷數組的元素,將它們傳入到異步函數中執行,其中的異步寫法容易寫錯,我們來看壹下有哪些易錯點。

假設我們有個異步方法 sleepPromise,形式如下:

這裏為了方便演示,使用 setTimeout 寫成了個 promise 形式的 sleep 方法。傳入的 t 為延遲執行的時間,msg 為信息內容。

在實際開發中,異步方法可能是傳入用戶好友 id 查找數據庫,獲得簡單的好友信息。

假設我們需要在下面代碼的註釋位置下方寫壹個異步便利實現。

通常前端壹看到要遍歷數組,就會用 forEach。如果妳不夠老道,可能會寫出如下的實現:

輸出結果為;

這種寫法並不對,其實是將遍歷寫成了同步。

問題出在哪?出在 forEach 本身並不支持異步寫法,妳在 forEach 方法的前面加不加 await 關鍵字都是無效的,因為它的內部沒有處理異步的邏輯。

forEach 是 ES5 的 API,要比 ES6 的 Promise 要早的多得多。為了向後兼容,forEach 以後也不會支持異步處理。

所以 forEach 的執行並不會阻塞 loopAsync 之後的代碼,所以會導致阻塞失敗,先輸出 [end] 。

使用普通的 for 循環寫法,await 的外層函數就仍就是 loopAysnc 方法,就能正確保存阻塞代碼。

但這裏的問題是,這些異步方法的執行是 串行 的。可以看到總***執行了 6 s。

如果我們的這些請求是有順序的依賴關系的,這樣寫是沒問題。

但如果我們的場景是根據用戶 id 數組從數據庫中查找對應用戶名,我們的時間復雜度就是 O(n) ,是不合理的。

此時我們需要改寫為 並行 的異步,並且還要保證所有異步都執行完後才執行下壹步。我們可以用 Promise.all() 。

首先,我們需要根據 tasks 數組生成對應的 promise 對象數組,然後傳入到 Promise.all 方法中執行。

這樣,這些異步方法就會同時執行。當所有異步都執行完畢後,代碼才往下執行。

輸出結果如下:

3 秒就完事了,太強了。

前面說到 forEach 底層並沒有實現異步的處理,才導致阻塞失效,那麽我們其實不妨實現支持異步的簡易 forEach。

並行實現:

串行實現:

用法:

簡單總結壹下。

壹般來說,我們更常用 Promise.all 的並行執行異步的方法,常見於數據庫查找壹些 id 對應的數據的場景。

for 循環的串行寫法適用於多個異步有依賴的情況,比如找最終推薦人。

forEach 則是純粹的錯誤寫法,除非是不需要使用 async/await 的情況。

  • 上一篇:ActiveX是什麽鬼?銀行密碼保密有什麽作用?
  • 下一篇:DSP,ARM和單片機的區別
  • copyright 2024編程學習大全網