Appearance
思路: pool为多少,就创建多少个工作区,每个工作区最多只有一个任务,任意一个工作区执行完任务后如果是成功的就继续添加任务执行, 到最后发现没有任务了 --> 成功 一旦中间过程有某个任务失败 --> 失败
javascript
function createRequest (tasks, pool) {
pool = pool || 5
let result = [],
together = new Array(pool).fill(null),
index = 0
together = together.map(() => {
// 通过Promise判断成功还是失败
return new Promise((resolve, reject) => {
const run = function run () {
if (index >= tasks.length) {
// 所有任务都能执行完,说明成功了
resolve()
return
}
// 取出任务
let indexBackUp = index,
task = tasks[index++]
task().then(val => {
// 如果成功,添加结果,保证结果顺序
result[indexBackUp] = val
// 成功了递归执行下一个任务
run()
}).catch(reason => {
// 有一个失败,整个工作区都失败
reject(reason)
})
}
run()
})
})
return Promise.all(together).then(() => result)
}
createRequest(tasks, 2).then(val => {
// 都成功,整体才成功,按顺序存储结果
console.log(val)
}).catch(reason => {
// 只要有一个失败,整体就是失败
console.log(reason)
})思路: 只有一个工作区, 开始没有任务, 每次放入一个任务并尝试执行 如果能执行说明
js
function createRequest2 (tasks, pool, callback) {
if (typeof pool === 'function') {
callback = pool
pool = 2
}
if (typeof pool !== 'number') pool = 2
if (typeof callback !== 'function') callback = Function.prototype
class TaskQueue {
// 执行的任务总数
running = 0
// 任务队列
queue = []
// 结果数组
result = []
pushTask (task) {
let self = this
self.queue.push(task)
// 每次放入一个任务都尝试执行
self.next()
}
// 执行
next () {
let self = this
// 执行任务的条件
while(self.running < pool && self.queue.length) {
// 执行数量+1
self.running++
// 从任务队列中取出该任务执行
let task = self.queue.shift()
task().then(val => {
// 成功则保存结果
self.result.push(val)
}).finally(() => {
// 不管成功/失败, 这个任务都执行完了
self.running--
// 执行下一个任务
self.next()
})
}
console.log(self.running)
if (self.running === 0) callback(self.result)
}
}
let taskQueue = new TaskQueue
tasks.forEach(task => taskQueue.pushTask(task))
}
createRequest2(tasks, 2, val => {
console.log(val)
})使用队列, 初始化时任务进队直到队列满, 执行队列任务直到所有任务执行完, 再进队...
js
class Queue {
constructor (limit) {
this.queue = []
this.limit = limit ? limit : Number.MAX_SAFE_INTEGER
}
offer (val) {
if (this.size() >= this.limit) {
return false
} else {
this.queue.push(val)
return true
}
}
poll () {
if (this.isEmpty()) {
return null
} else {
return this.queue.shift()
}
}
peek () {
if (this.isEmpty()) {
return null
} else {
return this.queue.shift()
}
}
peek () {
if (this.isEmpty()) {
return null
} else {
let { queue } = this
return queue[queue.length - 1]
}
}
size () {
return this.queue.length
}
isEmpty () {
return this.size() === 0
}
}javascript
class Scheduler {
constructor (tasks, limit, cb) {
this.originalTask = tasks
this.tasks = tasks.slice()
this.cb = cb
this.limit = limit
this.result = []
this.queue = []
// 装载任务
this.load()
}
load () {
const { tasks, queue, limit } = this
let task = null
// 装满
while (queue.length < limit && tasks.length > 0) {
queue.unshift(tasks.shift())
}
// 清空任务
this.flush()
}
flush () {
const { queue, result, cb, limit, originalTask } = this
let running = 0
// 所有任务都执行完了
if (!queue.length) {
return cb(result)
}
while (queue.length) {
// 取出任务并执行
const task = queue.shift()
const index = originalTask.indexOf(task)
task().then(val => {
// 保存结果
result[index] = val
running++
if (running === limit) {
// 重新装载任务
this.load()
}
}, reason => {
return callback(reason)
})
}
}
}
function scheduler (tasks, limit, callback) {
new Scheduler(tasks, limit, callback)
}
scheduler(tasks, 1, val => {
console.log(val)
})