每个已解决的

时间:2017-12-04 15:10:16

标签: javascript dictionary concurrency promise bluebird

我有一系列网址,我正在映射(使用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)

如何以理想的方式完成?感谢。

2 个答案:

答案 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 doThisdoThat。)

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()