NodeJS中的等forEach的邏輯都執行完


先貼代碼

const urls = torrentParser.urls()
const peers = []

let count = 0
await new Promise( (resolve) => {
    urls.forEach( async (url) => {
        try {
            const res = await getPeers(url, torrentParser.infoHash(), torrentParser.size(), 15 * 1000)
            for (const peer of res.peers) {
                peers.push(peer)
            }
        } catch (e) {
            logger.error(e)
        } finally {
            count += 1
            if ( count === urls.length ) {
            resolve()
            }
        }
    })
})

這段代碼要實現的邏輯是

 

我有很多urls,我想一下子訪問所有的urls,然后得到結果,這里的結果是peers的信息。

 

我不想用for loop,因為我的getPeers是寫成了同步函數的概念(要么返回結果,要么timeout),所以如果用for loop的話,就要一個一個url的訪問,一個一個urlblocking

 

所以就用forEach了。但是我希望我接下來的邏輯是要等所有的request都完成了才進行。這里就又用到了promise。新建一個promise,然后await住它,就是要等它要么reject(),要么resolve()。這里沒有要拋出錯誤,就沒用reject,只用了resolve。等到所有的request都返回了,我就可以resolve了。一開始的方案是可以使用forEachindex參數,當index參數等於array的長度減一的時候就可以resolve這個promise了。但是后來發現因為有些request會有錯誤,會跑到catch中去。所以就引入了finally,在finally里面我自己累計下返回的request數量,當累計到了所有的request后,就resolve了。因為無論try還是catch都要執行finally的邏輯。

 

理解的核心還是nodejs異步單線程的編程語言

即使感覺forEach好像是同時array里面所有的element就同時處理。(這里不是golang的協程,或者c++的多線程,它們是真的同時)。實際上,還是所有的element的處理是一個一個的處理,不同的是,不是處理完一個再來下一個,而是如果blocking了,就進行下一個,然后所有處理好的結果再排隊在一個callback的結果隊列中,一個一個的再被處理。

此話題在stack overflow有被討論

https://stackoverflow.com/questions/38406920/best-way-to-wait-for-foreach-to-complete/60646112#60646112

此代碼的完整代碼在這里

https://github.com/tw7613781/bittorrent/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM