2017年4月29日 星期六

(js)_.debounce_b

////////////////////////////////////////////////////////////////////////////////
/**
 * _.debounce_b
 *
 * 1.0.1
 *
 * 2017-4-14
 *
 * 減輕高頻執行事件的執行頻率
 *
 * for backbone.js event
 *
 */
////////////////////////////////////////////////////////////////////////////////
!(function (root) {
    // 被引用了嗎

    if (typeof _ === 'function') {
        _.mixin({
            debounce_b: debounce_
        });
    } else if (typeof module === 'object' && typeof module.exports === 'object') {
        module.exports = debounce_;
    } else {
        return;
    }
    /* ====================================================================== */
    /**
     * @param {int} wait: 要超過多少時間間隔才執行
     * @param {function} job: 要執行的事
     *
     */
    function debounce_(callback, wait) {
        var d = new Debounce({
            callback: callback,
            waitTime: wait
        });
        return d.proxy_fn();
    };
    ////////////////////////////////////////////////////////////////////////////
    // core
    function Debounce(option) {
        var self = this;

        this.waitTime = 5;
        this._waitTime;
        /* ---------------------------------- */
        this._callback;
        this.timeHandle;
        this.dataList = [];
        this.checkTime;
        /* ================================================================== */
        // 建構式
        (function () {
            (option !== Object(option)) && (option = {});

            (typeof option.waitTime === 'number') && (this.waitTime = option.waitTime);
            (typeof option.callback === 'function') && (this._callback = option.callback);

            this.check();
        }).call(this);
    }
    ////////////////////////////////////////////////////////////////////////////
    (function () {
        /**
         * 暴露在外的函式
         * 外部呼叫此
         */
        this.proxy_fn = function () {
            return function (data) {
                this._check(data);
            }.bind(this);
        };
        /* ================================================================== */
        this._check = function (data) {
            // 記錄每次呼叫傳來的資料
            this.dataList.push(data);

            // 更新時間
            this.checkTime = (new Date()).getTime();

            this._bindTimeCheck();
        };
        /* ================================================================== */
        this._bindTimeCheck = function () {
            if (!this.timeHandle) {
                console.log('no lock but will lock');
                this._waitTime = this._waitTime || this.waitTime;

                this.timeHandle = setTimeout(function () {
                    console.log('open lock');
                    this.timeHandle = undefined;
                    this._timeEnd();
                }.bind(this), this._waitTime);
            } else {
                console.log('is lock');

            }
        };
        /* ================================================================== */
        this._timeEnd = function () {
            var now = (new Date()).getTime();
            var diff = now - this.checkTime;

            console.log('timeCheck: 離上一次激發時間: ', diff);

            if (diff < this.waitTime) {

                // 未過時間檢測間隔
                this._waitTime = this.waitTime - diff;

                console.log('will lock agin: 上鎖時間: ', this._waitTime);

                this._bindTimeCheck();
            } else {
                // 已過時間檢測間隔

                console.log('finish');

                this._waitTime = undefined;

                // 執行任務
                this._doJob();
            }
        };
        /* ================================================================== */
        this._doJob = function () {
            var self = this;

            // 執行任務
            this._callback(this.dataList);

        };
        /* ================================================================== */
        this.check = function () {
            var error_array = [];

            if (!this._callback) {
                error_array.push('no setting function');
            }

            if (error_array.length > 0) {
                throw new Error(error_array.join(' | '));
            }
        };
    }).call(Debounce.prototype);

})(this || {});