62 lines
1.6 KiB
JavaScript
62 lines
1.6 KiB
JavaScript
const checkConcurrency = (concurrency = 1) => {
|
|
if (concurrency == null) {
|
|
concurrency = 1
|
|
}
|
|
else if (concurrency === 0) {
|
|
throw new Error('Concurrency must not be zero')
|
|
}
|
|
return concurrency
|
|
}
|
|
|
|
const onlyOnce = (fn) => (...args) => {
|
|
if (fn === null) {
|
|
throw new Error('Callback was already called')
|
|
}
|
|
const callFn = fn
|
|
fn = null
|
|
return callFn(...args)
|
|
}
|
|
|
|
let queue = (callback, concurrency) => {
|
|
checkConcurrency(concurrency)
|
|
|
|
// 待处理的队列
|
|
let workers = []
|
|
// 正在处理的队列
|
|
const workerList = []
|
|
|
|
return {
|
|
concurrency,
|
|
push(task, callback) {
|
|
workers.push({
|
|
task,
|
|
callback,
|
|
})
|
|
setTimeout(() => {
|
|
this.process()
|
|
}, 0)
|
|
},
|
|
process() {
|
|
while (this.concurrency > workerList.length && workers.length) {
|
|
const worker = workers.shift()
|
|
workerList.push(worker)
|
|
callback(worker.task, onlyOnce((...args) => {
|
|
this.pull(worker)
|
|
if (typeof worker.callback === 'function') {
|
|
worker.callback(...args)
|
|
}
|
|
this.process()
|
|
}))
|
|
}
|
|
},
|
|
pull(worker) {
|
|
const index = workerList.indexOf(worker)
|
|
if (index !== -1) {
|
|
workerList.splice(index, 1)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
uni.queue = queue((task, callback) => task(callback), 10)
|