假設我們有壹個異步方法sleepPromise,其形式如下:
這裏為了演示方便,用setTimeout寫了壹個promise形式的睡眠方法。傳入的t是延遲執行的時間,msg是信息內容。
在實際開發中,異步方法可能是傳入用戶的好友id來查找數據庫,得到簡單的好友信息。
假設我們需要在下面代碼的註釋位置下面寫壹個異步的方便實現。
通常前端壹看到要遍歷的數組就會使用forEach。如果您不夠成熟,您可以編寫以下實現:
輸出結果是:
這種寫法不對,其實就是把遍歷寫成同步。
有什麽問題?forEach本身不支持異步編寫,所以如果在ForEach方法前面加上await關鍵字是無效的,因為裏面沒有處理異步的邏輯。
ForEach是ES5的API,比ES6的承諾要早很多。為了向後兼容,ForEach將來將不支持異步處理。
所以forEach的執行不會阻塞loopAsync之後的代碼,所以會導致阻塞失敗,先輸出[end]。
使用普通的for循環編寫,await的外層函數仍然是loopAysnc方法,可以正確保存阻塞代碼。
但是這裏的問題是這些異步方法的執行是串行的。可見總* * *執行了6 s。
如果我們的請求有順序依賴,這樣寫是沒有問題的。
但如果我們的場景是根據用戶id數組從數據庫中找到對應的用戶名,我們的時間復雜度是O(n),這是不合理的。
此時,我們需要將其重寫為並行異步,並且我們必須確保在執行下壹步之前執行所有異步。我們可以使用Promise.all()。
首先我們需要根據tasks數組生成對應的promise對象數組,然後傳入Promise.all方法執行。
這樣,這些異步方法將被同時執行。當所有的異步都被執行後,代碼將被執行。
輸出結果如下:
三秒鐘就搞定了。太強了。
如前所述,forEach底層沒有實現異步處理,導致阻塞失敗,我們不妨實現壹個簡單的支持異步的forEach。
並行實現:
串行實現:
用法:
簡單總結壹下。
壹般來說,我們經常使用Promise.all的並行執行異步方法,常見於數據庫查找壹些id對應的數據的場景。
for循環的串行編寫適用於多個異步和依賴的情況,比如尋找最終裁判。
ForEach純粹是個錯誤,除非妳不需要使用async/await。