2017年4月14日 星期五

(js)underscore_throttle



_.throttle = function(func, wait, options) {
        var timeout; // timeHandle

        var context, args, result;
        var previous = 0;

        if (!options) {
            options = {};
        }
        /* ---------------------------------- */
        var later = function() {
            previous = options.leading === false ? 0 : _.now();

            timeout = null; // timeHandle 開鎖

            result = func.apply(context, args);

            if (!timeout) {
                context = args = null;
            }

        };
        /* ---------------------------------- */
        var throttled = function() {
            console.log('-----------------------');
            var now = _.now();

            // previous 要等開鎖後才會更新
            if (!previous && options.leading === false) {
                previous = now;
            }

            // 還有多久到
            var remaining = wait - (now - previous);

            context = this;
            args = arguments;
            console.log('remaining: ', remaining);

            if (remaining <= 0 || remaining > wait) {
                // 避免計時器超時未開鎖
                // 主要是這個 remaining <= 0
                // 若過了 wait.time 鎖尚未打開
                // 強制開鎖

                console.log('a');

                if (timeout) {
                    // 清除鎖
                    clearTimeout(timeout);
                    timeout = null;
                }
                previous = now;
                result = func.apply(context, args);
                if (!timeout) {
                    context = args = null;
                }
            } else if (!timeout && options.trailing !== false) {
                // 開鎖了
                console.log('b: ', remaining);

                // 設置一個時間,並上鎖
                timeout = setTimeout(later, remaining);
            }

            console.log('c: ', remaining);
            return result;
        };
        /* ---------------------------------- */
        throttled.cancel = function() {
            console.log('cancal');
            clearTimeout(timeout);
            previous = 0;
            timeout = context = args = null;
        };
        /* ---------------------------------- */
        return throttled;
    };