Skip to content

Instantly share code, notes, and snippets.

@zheeeng
Created March 17, 2019 14:37
Show Gist options
  • Save zheeeng/dadaa774395f8a4f504b99e04ab91e92 to your computer and use it in GitHub Desktop.
Save zheeeng/dadaa774395f8a4f504b99e04ab91e92 to your computer and use it in GitHub Desktop.
const race = async function * (size, taskIter) {
const queue = []
// enqueue
while (queue.length < size) {
const nextTask = taskIter.next()
if (!nextTask.done) {
queue.push(nextTask.value())
} else {
break
}
}
while (queue.length) {
await Promise.race(queue)
const winnerIndex = await Promise.race(queue.map((item, i) => item.then(_ => i)))
const winner = queue[winnerIndex]
const nextTask = taskIter.next()
if (!nextTask.done) {
// replace and enqueue
queue.splice(queue.findIndex(qt => qt === winner), 1, nextTask.value())
} else {
queue.splice(queue.findIndex(qt => qt === winner), 1)
}
yield winner
}
}
const limitExec = async (tasks, size) => {
const taskIter = tasks[Symbol.iterator]()
const result = []
for await (let winnerValue of race(size, taskIter)) {
result.push(winnerValue)
}
return result
}
const testTasks = Array.from(
{ length: 12 },
(_, index) => () => new Promise(resolve => setTimeout(resolve, Math.random() * 5000, index))
)
limitExec(testTasks, 3).then(console.log)
@zheeeng
Copy link
Author

zheeeng commented May 5, 2019

async function parallel(tasks, num) {
  let waiting
  let executing

  function resolveTask (task) {
    const taskPromise = task()
    taskPromise.then(() => {
      executing = executing.filter(t => t != taskPromise)
      if (waiting.length) {

        executing = executing.concat(resolveTask(waiting[0]))
        waiting.shift()
      }
    })
    return taskPromise
  }

  waiting = tasks.slice(num)
  executing = tasks.slice(0, num).map(resolveTask)

  const result = []
  while (executing.length) {
    result.push(await Promise.race(executing))
  }

  return result
}

const testTasks = Array.from(
  { length: 12 },
  (_, index) => () => new Promise(resolve => setTimeout(resolve, Math.random() * 1000, index)).then(i => (console.log(i), i))
)

parallel(testTasks, 3).then(console.log)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment