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的访问,一个一个url的blocking。
所以就用forEach了。但是我希望我接下来的逻辑是要等所有的request都完成了才进行。这里就又用到了promise。新建一个promise,然后await住它,就是要等它要么reject(),要么resolve()。这里没有要抛出错误,就没用reject,只用了resolve。等到所有的request都返回了,我就可以resolve了。一开始的方案是可以使用forEach的index参数,当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://github.com/tw7613781/bittorrent/