I could make an ad-hoc debounce function.. debounce as in it'll run n milliseconds AFTER it's finished calling.. surprisingly, 0 milliseconds would still occur after an instruction written below it.. using that logic, here's an example
var debObj={}; //empty object SOLELY for temporary storage of the debounce function
function debounce(fn,n,obj){ //debounce function
  function doIt(){
    obj[fn.toString()]=[fn,setTimeout(()=>{
      fn();delete(obj[fn.toString()])
    },n)]
  }
  if(obj[fn.toString()]){
    clearTimeout(obj[fn.toString()][1])
    doIt(); return;
  }
  doIt(); return;
}
function debouncer(fn,n){return function(){debounce(fn,n,debObj)}} //debounce function that imitates the functionality of the real debounce
//now for your code snippet...............................................................
let data = []
let logIt=debouncer(()=>console.log(data),0)
sources.forEach((src) => {
    parser.parseURL(src.rss, (err, feed) => {
        data.push(feed)
    })
    logIt()
})
I know it's extremely adhoc.. but does it work?