promise顺序执行的多种方案
回调形式
js
const f1 = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
console.log('p1 runing')
resolve(1)
}, 1000)
})
const f2 = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
console.log('p2 runing')
resolve(2)
}, 1000)
})
// 使用回调形式
f1().then(() => {
f2()
})
async、await 的方案
js
// 使用async await
async function asyncPromise() {
await f1()
f2()
}
reduce 方案
js
const arr = [f1, f2]
const runPromiseInsequence = (array, value) =>
array.reduce((promiseChain, currentFunction) => promiseChain.then(currentFunction), Promise.resolve(value))
runPromiseInsequence(arr, 'init')
递归方案
js
// 使用递归
const arr = [f1, f2]
function sequencePromise(arr) {
const pro = arr.shift()
if (pro) {
pro().then(() => {
sequencePromise(arr)
})
}
}
sequencePromise(arr)
任务队列
普通任务队列
js
class Queue {
constructor() {
let waitingQueue = []
let isRunning = false //记录是否有未完成的任务
function execute(task, resolve, reject) {
task()
.then(data => {
resolve(data)
})
.catch(e => {
reject(e)
})
.finally(() => {
//等待任务队列中如果有任务,则触发它;否则设置isRunning = false,表示无任务状态
if (waitingQueue.length) {
const next = waitingQueue.shift()
execute(next.task, next.resolve, next.reject)
} else {
isRunning = false
}
})
}
return function (task) {
return new Promise((resolve, reject) => {
if (isRunning) {
waitingQueue.push({ task, resolve, reject })
} else {
isRunning = true
execute(task, resolve, reject)
}
})
}
}
}
const queue = new Queue()
const task1 = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('task1')
}, 3000)
})
const task2 = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('task2')
}, 1000)
})
const queue = new Queue()
queue(task1).then(data => console.log(data))
queue(task2).then(data => console.log(data))
//result
//task1
//task2
有时间间隔的任务队列
实现一个有时间间隔,并且超时后会中断任务的任务队列
有几个要点:超时后终止当前任务直接开始下一个任务;delay 时间后才会执行下一个任务;如果任务 delay 了但没超时,则需要立即执行下一个任务
js
class Queue {
constructor({ delay, timeout }) {
let timer = null //当有任务执行时,设置超时检测的定时器
let waitingQueue = [] //等待任务的队列
function execute(task, resolve, reject) {
let resolved = false //记录任务是否结束
let executeNext = false //记录是否任务结束后,立即执行下一个任务
let isTimeout = false // 是否超时
task().then(data => {
// 超时了,这个任务完成也不管了
if (isTimeout) return // fix 原来没写着一行
//任务未超时,则会进入这里
resolve(data)
resolved = true //标记任务完成
clearTimeout(timer) //清除超时计时器
timer = null
if (executeNext) {
//true代表任务是在delay后完成的,所以直接执行下一个任务
const next = waitingQueue.shift()
if (next) {
execute(next.task, next.resolve, next.reject)
}
}
})
timer = setTimeout(() => {
isTimeout = true
reject('超时') //超时直接调用reject
timer = null
const next = waitingQueue.shift()
if (next) {
//立即执行下一个任务
execute(next.task, next.resolve, next.reject)
}
}, timeout)
//delay时间后,自动执行下一个任务
setTimeout(() => {
if (resolved) {
//true代表上一个任务已经完成,可以直接执行下一个任务
const next = waitingQueue.shift()
if (next) {
execute(next.task, next.resolve, next.reject)
}
}
executeNext = true //标记当前任务完成后,立即执行下个任务(给任务在delay之后完成用)
}, delay)
}
return function (task) {
return new Promise((resolve, reject) => {
if (!timer) {
//没有任务,则直接执行
execute(task, resolve, reject)
} else {
//否则 将任务放入等待队列中
waitingQueue.push({ task, resolve, reject })
}
})
}
}
}
const task1 = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('task1')
}, 3000)
})
const task2 = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('task2')
}, 2000)
})
const task3 = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('task3')
}, 1000)
})
const queue = new Queue({ delay: 2000, timeout: 3000 })
queue(task1).then(data => console.log(data))
queue(task2).then(data => console.log(data))
queue(task3).then(data => console.log(data))
//task1
//task2
//task3
const task4 = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('task4')
}, 4000)
})
queue(task4).then(data => console.log(data))
queue(task1).then(data => console.log(data))
queue(task2).then(data => console.log(data))
queue(task3).then(data => console.log(data))
//Uncaught (in promise) 超时
//task1
//task2
//task3