Javascript Promise.map和每个已解决问题的回调

Javascript Promise.map和每个已解决问题的回调,javascript,dictionary,concurrency,promise,bluebird,Javascript,Dictionary,Concurrency,Promise,Bluebird,我有一个URL数组,我正在映射(使用bluebird的诺言.map)到http GET请求,并设置最大并发集: const fetchingPages = Promise.map(urls, async url => { const data = await fetchPage(url) return data }, { concurrency: 100 }) const pages = await fetchingPages 我如何倾听每个承诺的解决,并以有组织的方式做一些副作

我有一个URL数组,我正在映射(使用bluebird的诺言.map)到http GET请求,并设置最大并发集:

const fetchingPages = Promise.map(urls, async url => {
  const data = await fetchPage(url)
  return data
}, { concurrency: 100 })
const pages = await fetchingPages
我如何倾听每个承诺的解决,并以有组织的方式做一些副作用,即不要将副作用放在内部。映射回调

理想情况下,我希望提前得到一个“空/伪”承诺数组,这样我就可以在发送相应的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)

如何以理想的方式做到这一点?谢谢。

使用自定义事件处理程序怎么样

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

从您的评论来看,似乎您为在
map
回调中放入大量代码而烦恼。您不必像往常一样,将各种逻辑位放入离散的、可组合的函数中,然后调用它们。例如:

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
(当然,您只需等待
完成这项
完成这项
,如果它们也是异步的。)

或者用承诺条款代替异步/
等待

const fetchingPages = Promise.map(urls, url => {
  return fetchPage(url)
    .then(doThis)
    .then(data => /*...some condition...*/ ? doThat(data) : data)
}, { concurrency: 100 })
const pages = await fetchingPage

“我怎样才能听得见每个承诺都得到了解决,并以一种有组织的方式做一些副作用,即不将副作用放在内部。映射回调?”这样做有什么不组织的地方?你试图通过做其他事情来实现什么?我觉得承诺应该增加可组合性,但被迫将可能需要对特定承诺做出反应的所有代码放在单个回调中会产生反作用。我不知道怎么做。你不必把代码放在
map
回调中,你只需要从那里调用它。我知道我可以做到这一点,但我不想“收集”所有最终需要运行的代码,一旦承诺被解析到一个地方。我一直在考虑@asosnovsky建议的事件处理程序,但我认为我不需要重新发明它,因为我已经在使用承诺,它的设计(我认为)是为了让您可以在代码中的任何地方注册回调。@JozefMikuláš-您当然可以将映射部分与等待整体结果分开(有一次我想提出这个建议)。如果没有并发控制,只需使用
const promises=url.map(…)
获取映射,然后做任何你想在该数组中连接承诺的事情,然后最终通过
Promise等待结果。所有的
。你可以写一些东西来有效地做到这一点,但需要并发控制(但我认为你必须写它).FWIW。如果我不需要限制并发性,我会直接用array.map将URL数组映射到承诺数组,然后用数组中的任何承诺做任何我想做的事情。但是一旦我使用了promise.map,我就失去了传递单个承诺并将回调注册到任何地方的能力。好吧,至少你知道我现在正在尝试做什么。你知道吗我认为这是一种反模式的行为,或者说是一种奇怪的行为?如果有一个实际的util可以做到这一点,我认为它会非常有用。如果我的示例解决方案(在OP中)被包装在实用程序中,那是不是太糟糕了?谢谢。@JozefMikuláš:FWIW,我从来没有觉得有必要这样做。:-,这并不意味着我会称它为反模式。