2021SC@SDUSC
目录
2.on(name, action, context opt)
3.once(name, action, context opt)
6.success(action, context opt)
clay.async.Task类是对异步任务的处理,从而处理claygl中有关的任务。由上次分析可得clay.async.Task类能够处理异步任务,包括接收任务,创建任务,设置任务发生前后,事件出错时所触发的事件,以及判断任务是否完成,及其成功或失败,并且可以判断有无该任务等。
本次分析的clay.async.Task类的功能有移除事件监听器,注册事件处理程序,注册仅执行一次即销毁的事件处理程序,设置任务的成功和失败,注册success事件处理程序以及触发事件等。
该函数的作用是移除事件监听器。
参数有action,类型为function,表示所移除事件监听器的动作方法,context,类型为object,表示所移除事件监听器的内容。
其源代码如下:
off: function(name, action) {
var handlers = this.__handlers__ || (this.__handlers__={});
if (!action) {
handlers[name] = [];
return;
}
if (handlers[name]) {
var hdls = handlers[name];
var retains = [];
for (var i = 0; i < hdls.length; i++) {
if (action && hdls[i].action !== action) {
retains.push(hdls[i]);
}
}
handlers[name] = retains;
}
return this;
}
从源代码中可以看出,off方法接收了name和action这两个形式参数,name表示事件监听器的name,action表示事件监听器的action。首先,若本对象的__handlers__成员变量若不为空,则将其赋值给新创建的局部变量handlers,否则将handlers设置为空字典。
判断action形参,若action为空,则设置handlers中键为name的值为空数组,并返回。判断handlers,若其键为name的值不为空,即action不为空,则创建局部变量hdls,并将handlers[name]赋值给它。继续创建名为retains的空数组。对hdls进行遍历,若action不为空并且hdls中不存在与action一致的action值,则将hdls中符合该特性的action放入retains数组中,并将retains数组重新赋给handlers中键为name的值,通过这一方法,即可删除本对象中的action方法,从而移除事件监听器。最后返回本对象即可。
该函数能够注册事件处理程序。
参数有name,类型为string,表示事件处理程序的名称,action,类型为function,表示事件处理程序的动作方法,context,类型为object,表示事件处理程序的内容。
其源代码如下:
on: function(name, action, context) {
if (!name || !action) {
return;
}
var handlers = this.__handlers__ || (this.__handlers__={});
if (!handlers[name]) {
handlers[name] = [];
}
else {
if (this.has(name, action)) {
return;
}
}
var handler = new Handler(action, context || this);
handlers[name].push(handler);
return this;
}
从源代码中可以看出,接收的形参有三个,分别为name,action,context,分别表示事件处理程序的名称,动作方法,内容。首先,该函数判断时间处理程序的名称和动作方法是否为空,若其中一个为空,则返回。
接着,若本对象的__handlers__成员变量若不为空,则将其赋值给新创建的局部变量handlers,否则将handlers设置为空字典。
然后,判断handlers键为name的值是否为空,如果为空则将其初始化为空数组,否则,调用has函数,判断相应name和action的事件处理程序是否已经存在,若存在则返回。
最后,采用形参action和context创建一个Handler对象,并赋值给新建的handler局部变量,若context为空,则将本对象作为context。将handler加入到handlers中键为name的数组中即可,从而完成时间处理程序的注册。最后返回本对象。
该函数的作用是注册一个事件,该事件仅执行一次便移除。
参数有name,类型为string,表示事件的名称,action,类型为function,表示事件的动作方法,context,类型为object,表示事件的内容。
其源代码如下:
once: function(name, action, context) {
if (!name || !action) {
return;
}
var self = this;
function wrapper() {
self.off(name, wrapper);
action.apply(this, arguments);
}
return this.on(name, wrapper, context);
}
从源代码中可以看出,接收的形参有三个,分别为name,action,context,分别表示事件处理程序的名称,动作方法,内容。首先,该函数判断时间处理程序的名称和动作方法是否为空,若其中一个为空,则返回。
接着,创建一个局部变量self,并将本对象赋值给self。执行一个函数wrapper,对self变量调用off方法,移除wrapper事件监听器,接着,通过接收的参数,调用action的apply方法,执行action,从而实现执行该action方法,但执行后即移除该事件,从而实现仅执行一次该方法的作用。最后返回本对象的on函数的返回值,参数为name,wrapper和context。
该函数的作用是设置任务失败。
参数为err,表示失败事件。
其源代码如下:
Task.prototype.reject = function(err) {
this._rejected = true;
this._fullfilled = false;
this.trigger('error', err);
}
由源代码可以看出,该函数设置_rejected为true,表示任务失败,同时设置_fullfilled为false,也表示任务失败,设置标志位为失败后,调用trigger方法,传入参数'error'和err,触发内置的error方法,参数为err。
该函数的作用是设置任务成功。
参数为data,表示成功事件。
其源代码为:
Task.prototype.resolve = function(data) {
this._fullfilled = true;
this._rejected = false;
this.trigger('success', data);
}
由源代码可以看出,该函数设置_rejected为false,表示任务成功,同时设置_fullfilled为true,也表示任务成功,设置标志位为成功后,调用trigger方法,传入参数'success'和data,触发内置的success方法,参数为data。
该函数的作用是注册success事件处理程序。
参数为action,类型为function,表示success事件处理程序的动作方法发,context,类型为object,表示success事件处理程序的内容。
其源代码如下:
success: function(action, context) {
return this.once('success', action, context);
}
从源代码可以看出,该函数调用本对象的once方法,once方法能够注册时间处理程序。传入的参数有name,action和context,name固定为'success',最终实现success事件处理程序的注册。
该函数的作用是触发事件。
参数有name,类型为string,表示触发事件的名称。
其源代码如下:
trigger: function(name) {
if (!this.hasOwnProperty('__handlers__')) {
return;
}
if (!this.__handlers__.hasOwnProperty(name)) {
return;
}
var hdls = this.__handlers__[name];
var l = hdls.length, i = -1, args = arguments;
// Optimize advise from backbone
switch (args.length) {
case 1:
while (++i < l) {
hdls[i].action.call(hdls[i].context);
}
return;
case 2:
while (++i < l) {
hdls[i].action.call(hdls[i].context, args[1]);
}
return;
case 3:
while (++i < l) {
hdls[i].action.call(hdls[i].context, args[1], args[2]);
}
return;
case 4:
while (++i < l) {
hdls[i].action.call(hdls[i].context, args[1], args[2], args[3]);
}
return;
case 5:
while (++i < l) {
hdls[i].action.call(hdls[i].context, args[1], args[2], args[3], args[4]);
}
return;
default:
while (++i < l) {
hdls[i].action.apply(hdls[i].context, Array.prototype.slice.call(args, 1));
}
return;
}
}
从源代码可以看出,首先判断本对象是否有成员变量__handlers__,若无则返回,若有,则判断__handlers__中是否有键为name的值,若其值为空,则返回。
若以上两个条件均满足,则创建一个局部变量hdls,将本对象中__handlers__中键为name的值赋给它。获取hdls的长度赋给局部变量l,创建i为-1,args为参数arguments。
判断args参数的长度,若为1,则调用hdls中第一个对象的action方法,参数为hdls第一个对象的内容;若为2,则调用hdls中第一个对象的action方法,参数为hdls第一个对象的内容和args[1];若为3,则调用hdls中第一个对象的action方法,参数为hdls第一个对象的内容和args[1],args[2];若为4,则调用hdls中第一个对象的action方法,参数为hdls第一个对象的内容和args[1],args[2],args[3];若为5,则调用hdls中第一个对象的action方法,参数为hdls第一个对象的内容和args[1],args[2],args[3],args[4];否则,调用hdls中第一个对象的action方法,参数为hdls第一个对象的内容和所有的args参数。可见,该函数能够调用hdls中的方法,即__handlers__的方法,并以context和arguments参数来运行,从而实现事件的出发。