我有一系列网址,我正在映射(使用bluebird的Promise.map)到最大并发设置的http GET请求:
const fetchingPages = Promise.map(urls, async url => {
const data = await fetchPage(url)
return data
}, { concurrency: 100 })
const pages = await fetchingPages
我如何倾听每一个被解决的承诺,并以有组织的方式做一些副作用,即不要将副作用放在.map回调中?
理想情况下,我想拥有"空/虚拟"承诺提前,所以我可以在相应的GET请求被发送之前设置回调到其中任何一个。
我可以这样做:
const pagesUtils = urls.map((url) => {
let resolve, reject
const promise = new Promise((res, rej) => {
resolve = res
reject = rej
})
return {
url,
promise,
resolve,
reject,
}
})
const pagesPromises = pagesUtils.map(x => x.promise)
Promise.map(urlsFinal, async (url, i) => {
const data = await fetchPageData(url)
pagesUtils[i].resolve(data)
return data
}, { concurrency: CONCURRENCY })
pagesPromises.forEach(p => {
p.then((result) => {
// side-effect
console.log(result)
})
})
const results = await Promise.all(pagesPromises)
如何以理想的方式完成?感谢。
答案 0 :(得分:1)
从您的评论中,您似乎对在map
回调中添加了大量代码感到困扰。您不必将各种逻辑逻辑放入正常的离散可组合函数中,并调用它们。 E.g:
const fetchingPages = Promise.map(urls, async url => {
let data = await fetchPage(url)
data = await doThis(data)
if (/*...some condition...*/) {
data = await doThat(data)
}
return data
}, { concurrency: 100 })
const pages = await fetchingPage
(当然,如果他们也是异步的,您只需await
doThis
或doThat
。)
或async
/ await
const fetchingPages = Promise.map(urls, url => {
return fetchPage(url)
.then(doThis)
.then(data => /*...some condition...*/ ? doThat(data) : data)
}, { concurrency: 100 })
const pages = await fetchingPage
答案 1 :(得分:0)
如何使用自定义事件处理程序?
function URLFetcher(urls) {
var onCallback = () => {};
this.on = cb => {
onCallback = cb;
}
this.fetch = () => {
return Promise.map(urls, async (url, idx) => {
const data = await fetchPage(url);
onCallback(idx, url, data);
return data
}, { concurrency: 100 })
}
}
var fetcher = new URLFetcher(urls);
fetcher.on( (idx, url, data) => {
console.log(`URL #${idx} i.e ${url} was returned with data`, data);
})
const pages = await fetcher.fetch()