js-实现多任务调动

481 阅读2分钟

同步串行执行任务

几个异步同时执行,最后一个执行完毕调用一下回调方法

当多个任务要串行执行,结果要统一处理时,将多个任务放入队列中执行,直到所有任务结束才结束,一分钟执行 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');
})