当前位置: 首页 > 工具软件 > ClayGL > 使用案例 >

2021SC@SDUSC山东大学软件学院软件工程应用与实践——claygl(源代码分析7)

阙阳
2023-12-01

2021SC@SDUSC

目录

一.clay.async.Task类回顾

二.clay.async.Task类的扩展功能分析

三.clay.async.Task类源码分析(二)

1.off(action, context opt)

2.on(name, action, context opt)

3.once(name, action, context opt)

4.reject(err)

5.resolve(data)

6.success(action, context opt)

7.trigger(name)


一.clay.async.Task类回顾

    clay.async.Task类是对异步任务的处理,从而处理claygl中有关的任务。由上次分析可得clay.async.Task类能够处理异步任务,包括接收任务,创建任务,设置任务发生前后,事件出错时所触发的事件,以及判断任务是否完成,及其成功或失败,并且可以判断有无该任务等。

二.clay.async.Task类的扩展功能分析

    本次分析的clay.async.Task类的功能有移除事件监听器,注册事件处理程序,注册仅执行一次即销毁的事件处理程序,设置任务的成功和失败,注册success事件处理程序以及触发事件等。

三.clay.async.Task类源码分析(二)

1.off(action, context opt)

    该函数的作用是移除事件监听器。

    参数有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方法,从而移除事件监听器。最后返回本对象即可。

2.on(name, action, context opt)

    该函数能够注册事件处理程序。

    参数有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的数组中即可,从而完成时间处理程序的注册。最后返回本对象。

3.once(name, action, context opt)

    该函数的作用是注册一个事件,该事件仅执行一次便移除。

    参数有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。

4.reject(err)

    该函数的作用是设置任务失败。

    参数为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。

5.resolve(data)

    该函数的作用是设置任务成功。

    参数为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。

6.success(action, context opt)

    该函数的作用是注册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事件处理程序的注册。

7.trigger(name)

    该函数的作用是触发事件。

    参数有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参数来运行,从而实现事件的出发。

 类似资料: