别再看Promise 了,尝试下自己用JS 封装实现任务队列。

// 建议复制到编辑器里跑一下看看

function Model(tasksProperties){ }

Model.create = function(init) {
    function Model(taskProperties) {
        if (this instanceof Model) {
            this.__t = mixin({}, taskProperties);
            if (this.__init)
                this.__init(this.__t);
        } else {
            Model.add.call(Model, ...arguments);
        }
    }
    Model.add = add;
    return Model;
}
Model.add = add;
function add(method, ...tasks) {
    var proto = this.prototype;
    validateTasks(tasks);
    var cacheName = "__t_" + method;
    proto[cacheName] = proto[cacheName] || [];
    proto[cacheName] = proto[cacheName].concat(tasks);

    proto[method] = function(params, cb, progress) {
        var that = mixin({ params: params || {} }, this.__t);
        that.rootMethodName = method; //添加是调用方法的名字
        
           var self = this;
        that.model = self;
        if (arguments.length > 2) {
            that.progress = progress;
        }
        var after = self["__t_after"];
        series(self[cacheName], that, function(err, data) {
            that.data = data;
            if (after && after.length) {
                series(after, that, complete);
            } else {
                cb()
            }
        });
        return that;
    }
}
Model.prototype.after = after;

function after(tasks) {
    tasks = [].slice.call(arguments, 0);
    var cacheName = "__t_after";
    var proto = this;
    proto[cacheName] = proto[cacheName] || [];
    proto[cacheName] = proto[cacheName].concat(tasks);
}

function validateTasks(tasks) {
    for (var k in tasks) {
        var t = typeof tasks[k];
        if (t != "string" && t != "function" && !Array.isArray(tasks[k])) {
            throw new Error("Task must String, Function or Array: " + tasks[k]);
        }
    }
}



function emptyFunction() {}

function mixin(obj, source) {
    if (obj && source) {
        for (var key in source) {
            if(source.hasOwnProperty(key)){
                obj[key] = source[key]
            }
        }
    }
    return obj;
}
Model.series = series;

function series(tasks, that, callback, deepIndex) {

    callback = callback || emptyFunction;

    var completed = 0,
        len = tasks.length;
    if (!len) {
        return callback && callback();
    }
    deepIndex = deepIndex || 0;
    that.deepIndex = deepIndex;
    that.debug = that.debug || emptyFunction;

    function next(code, done) {
        if (code === undefined) {
            completed += 1;
        } else if (code === true) {
            return callback(that.error, that.data);
        } else if (code instanceof Error) {
            //Save error
            that.error = code;
            return callback(code);
        } else if (Array.isArray(code)) {
            //Call the next task list
            series(code, that, done ? done : function(err, data) {
                next(err ? err : undefined);
            }, deepIndex + 1);
            return;
        } else if (typeof code == "number") {
            if (code < 0) {
                code = len + code;
            }
            completed = code;
        } else if ((completed = tasks.indexOf(code)) == -1) {
            return callback(new Error("Unknown task for " + code));
        }

        if (completed >= len || completed < 0) {
            callback(that.error, that.data);
        } else {
            iterate();
        }
    }

    function iterate() {
        var task = tasks[completed];

        if (!len) {
            callback();
        } else if (typeof task == "string") {
            that.debug(deepIndex, task);
            next();
        } else if (task instanceof Function) {
            that.debug(deepIndex, task.name || "anonymous");
            if (!task.length) {
                //has not next
                next(task.call(that));
            } else {
                task.call(that, next);
            }
        } else if (Array.isArray(task)) {
            next(task);
        } else {
            throw Error("Unsupported task type");
        }
    }
    iterate();
}
var model =  Model.create('init') //可传入function 或者 obj 初始化定义

var requestApi = new model({ request: 'request', clearCookie: 'clearCookie', jsonError: true, os_type:'a'});

function fn5(next){
    setTimeout(() => {
        console.log('第五个任务函数')
        next()
    }, 1500);
}
function fn6(next){
    setTimeout(() => {
        console.log('第六个任务函数')
        next()
    }, 1000);
}
function fn7(next){
    setTimeout(() => {
        console.log('第七个任务函数')
        next()
    }, 500);
}
tasks = [fn5,fn6,fn7]

model('test',fn2,fn1,tasks,fn3,fn4)

function fn1(next){
    setTimeout(() => {
        console.log('第一个任务函数')
        if(Math.random() > 0.3){
            console.log('穿插')
            next([fn6,fn7],function(){
                console.log('中间穿插完成')
                next()
            })
        }else{
            next()
        }
    }, 1000);
}
function fn2(next){
    setTimeout(() => {
        console.log('第二个任务函数')
        next()
    }, 1000);
}
function fn3(next){ 
    setTimeout(() => {
        console.log('第三个任务函数')
        next()
    }, 1000);
}
function fn4(next){
    setTimeout(() => {
        console.log('第四个任务函数')
        next()
    }, 1000);
}

requestApi.test({a:'1',b:'2'},function(){
    console.log('callback done')
})
posted @ 2020-03-20 13:52  萝卜爱吃青菜  阅读(702)  评论(2编辑  收藏  举报