别再看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')
})