Skip to content

Instantly share code, notes, and snippets.

@oxyflour
Created September 19, 2020 17:08
Show Gist options
  • Save oxyflour/b5032d754fc4fc9ba4f6edfc29506d6b to your computer and use it in GitHub Desktop.
Save oxyflour/b5032d754fc4fc9ba4f6edfc29506d6b to your computer and use it in GitHub Desktop.
async reduce of array
async function reduce(arr, fn) {
let tasks = arr.map(item => ({ item })),
reqs = []
while (true) {
if (tasks.length === 1) {
return tasks[0].item
}
const toRun = tasks.filter(task => !task.started)
for (let i = 0; i + 1 < toRun.length; i += 2) {
const [a, b] = toRun.slice(i, i + 2)
a.started = b.started = true
const r = fn(a.item, b.item).then(item => {
tasks = tasks.filter(task => task !== a && task !== b).concat({ item, a, b })
reqs = reqs.filter(req => req !== r)
})
reqs.push(r)
}
await Promise.race(reqs)
}
}
function sleep(time) {
return new Promise(resolve => setTimeout(resolve, time))
}
async function it() {
const arr = Array(Math.floor(Math.random() * 5 + 1)).fill(0).map((_) => Math.random())
const ret = await reduce(arr, async function (a, b) {
await sleep(Math.random() * 2000)
console.log(a, b)
return a + b
})
console.log('assert', ret, '===', arr.reduce((s, a) => s + a, 0))
}
it()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment