在很多源码的框架中,会经常看到队列的实现,例如:js异步队列,vue生命周期,koa模型,webpack中plugins等
一.同步队列
同步队列很简单,通过for循环遍历就行了
let queue= []
...执行其他操作
queue.push(fn1)
...执行其他操作
queue.push(fn2)
...执行其他操作
queue.push(fn3)
...收集完成
function runQueue(){
for(let i=0;i<arr.length;i++){
arr[i]()
}
}
runQueue()
二.异步队列
1. 通过注入next,决定什么时候执行队列下一方法
let queue= []
queue.push(function(next){
setTimeout(()=>{
next() //异步后调用下一个队列
},1000)
})要实现这样的逻辑,需要把next方法暴露给用户,什么时候执行由用户决定
执行异步队列实现,如下:
function runQueue(queue,i, cb){
if(i<queue.length){
if(queue[i]){
queue[i](function next(){ //next函数暴露给用户
runQueue(queue,i+1,cb)
})
}else{
runQueue(queue,i+1,cb)
}
}else{
cb()
}
}
runQueue(queue,0,cb)2.promise函数自动执行next
如果push到队列中的函数返回的是promise,我们希望在resolve的时候,自动执行next
function runPromiseQueue(queue, i, cb) {
if (i < queue.length) {
if (queue[i]) {
let res = queue[i]()
if (res instanceof Promise) {
res.then(function next(args) {
runPromiseQueue(queue, i + 1,cb)
return args
})
} else {
runPromiseQueue(queue, i + 1,cb)
}
} else {
next(i + 1)
}
} else {
cb()
}
}为什么promise.then就能实现上面的这个方案
promise.then其实内部原理也是同过调用then方法往promise中resolvedQueue队列中push待执行的方法,resolvedQueue队列的执行时机是在执行resolve函数的时候,所以通过控制resolve方法的执行也就间接手动执行next的方法
promise源码实现:juejin.cn/post/684490…