总结:
这一个小节的内容,是把需要的任务方法添加到任务队列,然后将任务按照不同类型处理。
这里需要注意的是,每一个任务函数都要有处理callback的能力,这样才能next;
第一个任务,将任务添加到任务队列,是这样做的。在使用这个库的时候,demo会首先调用Animation.prototype.loadImage()这个方法。而在代码中,并不是直接调用预加载loadImage()方法,而是把这个方法定义为对象中的一个属性,并定义它的类型,然后将完成的对象加入一个列表中,并且返回this。
这个列表就是this.taskQueue.
格式: [{taskFn: taskFn,
type: type}]
Animation.prototype._add 将任务加入到任务队列中,
最终this._add返回this。这个this也被Animation.prototype.loadImage()最终返回。
代码:
Animation.prototype.loadImage = function (imageList) {
var taskFn = function (next) {
//为了保证不影响原对象。使用slice
loadImage(imageList.slice(),next)
}
//设置为同步任务。
var type = TASK_SYNC;
//放到任务队列中,同时返回由this._add()所返回的this
return this._add(taskFn, type);
}
Animation.prototype._add = function (taskFn, type) {
this.taskQueue.push({
taskFn: taskFn,
type: type
})
return this;
}
任务队列taskQueue已经有了。接下来就是执行里面的任务了。
通过调用Animation.prototype.start(),
设置了任务执行状态,以及时间间隔之后
这里调用的是,Animation.prototype._runTasks
_runTasks中,遍历并没有用for 语句,而是通过迭代。
代码:
Animation.prototype.start = function (interval) {
//当开始的时候,如果已经开始了,那么不动作
if (this.state === STATE_START) {
return this;
}
//如果没有任务
if (!this.taskQueue, length) {
return this;
}
this.state = STATE_START;
this.interval = interval;
this._runTasks();
return this;
}
通过在this上定义一个值为0的index属性,index会在完成任务的时候递增,并且在Index == 任务队列的长度的时候,也就是执行完所有任务的时候,停止执行,释放内存等。
代码:
function Animation() {
//任务队列
this.taskQueue = [];
//控制遍历的计数器
this.index = 0;
//执行状态
this.state = STATE_INITIAL
}
使用this.taskQueue[this.index]的形式取出当前方法。
index每次递增都会重新调动任务队列的执行函数_runTasks
_runTasks里面的逻辑是,
通过之前this._add的时候,设置的方法状态,来确定是异步还是同步。
代码:
Animation.prototype._runTasks = function() {
//所以呢,它应该是接收一个任务队列,然后按照异步或者同步的方式分别执行。
//在这里这个任务队列在实例上的taskQueue
if (!this.taskQueue.length || this.state !== STATE_START ) {
return;
}
//任务执行完毕,释放内存
if (this.index === this.taskQueue.length) {
this.dispose()
return;
}
//由于由this.index控制遍历,所以从当前任务开始,this.index默认为第一个
//这里已经是经过this._add后,对象的形式{taskFn: taskFn, type: type}
var task = this.taskQueue[this.index]
//task可能是同步任务或者异步任务,两种任务执行方式不同
if (task.type === TASK_SYNC) {
this._syncTask(task)
} else if (task.type === TASK_ASYNC) {
this._asyncTask(task)
}
}
这里this.index++,以及_runTasks的再次调用,是在同步或者异步任务执行完毕之后,由负责同步任务或者异步任务的函数来调用的。
代码:
/*执行同步任务的方法 */
Animation.prototype._syncTask = function (task) {
//保留this,因为会在闭包中调用。
var m = this
//执行完毕的回调
var next = function () {
me._next()
}
//取出要执行的方法
var taskFn = task.taskFn;
//执行它,并传入回调。
taskFn(next)
}
/*
*切换到下一个任务的方法
*/
Animation.prototype._next = function () {
this.index++;
//这里是遍历。
this._runTasks();
}
/**
* 异步任务执行方法
*/
Animation.prototype._asyncTask = function(task) {
//未待续完,使用requestAnimationFrame
}
Animation.prototype._runTasks 负责确定极限值的收尾工作,以及确定任务状态并且执行负责同步任务或者负责异步任务的函数。
所有的数据都由实例来负责。在实例上定义。