同步串行执行任务
几个异步同时执行,最后一个执行完毕调用一下回调方法
当多个任务要串行执行,结果要统一处理时,将多个任务放入队列中执行,直到所有任务结束才结束,一分钟执行 60 次
代码实现:
var mQueue = function () {
this.fnSources = [];
this.excuting = false;
// 添加任务队列数据,并存储(默认情况下:添加任务以及任务参数)
this.add = function (fn) {
// 类型检验,错误处理
if (typeof fn !== "function")
throw ("第一个参数必须是方法");
var args = Array.from(arguments).splice(1);
// 维护任务队列,将任务与任务参数添加到任务队列里
this.fnSources.push({
fn: fn,
args: args
})
};
// 添加任务:任务中含有执行上下文
this.addWithContext = function (context,fn) {
// 类型检验,错误处理
if (typeof fn !== "function")
throw ("第二个参数必须是方法");
var args = Array.from(arguments).splice(2);
this.fnSources.push({
fn: fn,
args: args,
context:context
})
};
// 初始化任务列表
this.clear = function () {
this.fnSources = [];
this.excuting = false;
}
// 执行下一个任务
this.next = function () {
// 如果上一个任务执行中,则不执行下一个任务
if (this.excuting){
return;
}
// 取出最新任务执行的方法
var fnObj = this.fnSources.splice(0, 1)[0];
// 执行方法,并将执行状态excuting更新,表示任务正在执行中
if (fnObj) {
// console.log('next:'+this.excuting)
this.excuting = true;
// 将this指向存入参数的第一个值中
fnObj.args.unshift(this);
fnObj.fn.apply(fnObj.context, fnObj.args);
}
}
// 结束任务
this.finished = function () {
// console.log('finished')
this.excuting = false;
}
// 因需要在setInterval中执行next方法,需要保存this上下文
var that = this;
setInterval(function () {
that.next();
}, 1000 / 60)
}
module.exports = mQueue
- 用 class 方法实现
class AsyncSerial{
constructor() {
this.cbList = [];
}
tap(fn) {
this.cbList.push(fn);
}
call(end){
let index = 0;
let next = () => {
if(index === this.cbList.length){
end();
return;
}
let fn = this.cbList[index];
fn(() => {
index++;
next();
})
}
next();
}
}
let ap = new AsyncSerial();
ap.tap((cb) => {
setTimeout(() => {
console.log(1);
cb();
}, 3000)
})
ap.tap((cb) => {
setTimeout(() => {
console.log(3);
cb();
}, 2000)
});
ap.call(() => {
console.log('end');
})
异步并行
多个任务同时进行,直到任务都完成了,才会清除执行栈
class AsyncParallel {
constructor() {
this.cbList = [];
}
tap(fn) {
this.cbList.push(fn);
}
call(end) {
let index = 0;
this.cbList.forEach(fn => {
fn(() => {
index++;
if (index === this.cbList.length) { end() };
});
})
}
}
let ap = new AsyncParallel();
ap.tap((cb) => {
setTimeout(() => {
console.log(1);
cb();
}, 3000)
})
ap.tap((cb) => {
setTimeout(() => {
console.log(3);
cb();
}, 1000)
});
ap.call(() => {
console.log('end');
})