2016-05-31 12 views
2

jqueryuiのスライダウィジェットを使用しています。
スライダのスライドイベントで機能を実行したいのですが、(700ms)遅延後にのみ実行します。スライダハンドルが動き続けている(すなわち、再びスライドをトリガする)場合、遅延タイムアウトをリセットしたい。スライドイベントの遅延コールバック関数

jqueryのdoTimeoutとsetTimeoutを無駄に使用しようとしました。私がしていることは、スライダのハンドルが位置を変えるのを防ぐためです。

var heavy = { 
    updatesomething: function() { 
     //some computationally heavy code 
    } 
} 

$('#slider').slider({ 
    min:1, max:99, orientation: 'vertical', 
    slide: function(event, ui) { 
     $(this).doTimeout('timeoutid', 700, function() { 
      heavy.updatesomething(this, ui.value); }); 
    } 
}); 

答えて

0

利用可能なデバウンスの実装を使用します。以下の例はdavidwalsh blogから取られます。コンテキストを回す代わりに、右のコンテキストと引数で関数を呼び出すには、次のようにapplyを使用します。

var heavy = { 
 
    updatesomething: function(event, ui) { 
 
    console.log(this); 
 
    console.log(ui); 
 
    } 
 
} 
 

 
// taken from https://davidwalsh.name/javascript-debounce-function 
 
function debounce(func, wait, immediate) { 
 
    var timeout; 
 
    return function() { 
 
    var context = this, 
 
     args = arguments; 
 
    var later = function() { 
 
     timeout = null; 
 
     if (!immediate) func.apply(context, args); 
 
    }; 
 
    var callNow = immediate && !timeout; 
 
    clearTimeout(timeout); 
 
    timeout = setTimeout(later, wait); 
 
    if (callNow) func.apply(context, args); 
 
    }; 
 
}; 
 

 
$('#slider').slider({ 
 
    min: 1, 
 
    max: 99, 
 
    orientation: 'vertical', 
 
    slide: debounce(function(event, ui) { 
 
    heavy.updatesomething.apply(this, arguments); 
 
    //---------------------------^-context ^-- what it says 
 
    }, 700) 
 
});
<link href="//code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css" rel="stylesheet" /> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script> 
 
<div id="slider"></div>

0

この場合、デバウンスの問題は、ユーザーがスライダーを動かし続ける場合はイベントがないことです。したがって、スロットリングを使用する方が便利です。

また、以下の例では、完全lodashスロットルとデバウンス

'use strict'; 
 

 
/** 
 
* Creates a debounced function that delays invoking `func` until after `wait` 
 
* milliseconds have elapsed since the last time the debounced function was 
 
* invoked. The debounced function comes with a `cancel` method to cancel 
 
* delayed `func` invocations and a `flush` method to immediately invoke them. 
 
* Provide `options` to indicate whether `func` should be invoked on the 
 
* leading and/or trailing edge of the `wait` timeout. The `func` is invoked 
 
* with the last arguments provided to the debounced function. Subsequent 
 
* calls to the debounced function return the result of the last `func` 
 
* invocation. 
 
* 
 
* **Note:** If `leading` and `trailing` options are `true`, `func` is 
 
* invoked on the trailing edge of the timeout only if the debounced function 
 
* is invoked more than once during the `wait` timeout. 
 
* 
 
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred 
 
* until to the next tick, similar to `setTimeout` with a timeout of `0`. 
 
* 
 
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) 
 
* for details over the differences between `_.debounce` and `_.throttle`. 
 
* 
 
* from lodash - https://github.com/lodash/lodash/blob/4.16.2/lodash.js#L10218 
 
*/ 
 
function debounce(func, wait, options) { 
 
\t if (!options) options = {}; 
 

 
\t let lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, 
 
\t \t leading = false, 
 
\t \t maxing = false, 
 
\t \t trailing = true; 
 

 
\t wait = wait || 0; 
 
\t leading = !!options.leading; 
 
\t maxing = 'maxWait' in options; 
 
\t maxWait = maxing ? Math.max(options.maxWait || 0, wait) : maxWait; 
 
\t trailing = 'trailing' in options ? !!options.trailing : trailing; 
 

 
\t function invokeFunc(time) { 
 
\t \t const args = lastArgs, 
 
\t \t \t thisArg = lastThis; 
 

 
\t \t lastArgs = lastThis = undefined; 
 
\t \t lastInvokeTime = time; 
 
\t \t result = func.apply(thisArg, args); 
 
\t \t return result; 
 
\t } 
 

 
\t function leadingEdge(time) { 
 
\t \t // Reset any `maxWait` timer. 
 
\t \t lastInvokeTime = time; 
 
\t \t // Start the timer for the trailing edge. 
 
\t \t timerId = setTimeout(timerExpired, wait); 
 
\t \t // Invoke the leading edge. 
 
\t \t return leading ? invokeFunc(time) : result; 
 
\t } 
 

 
\t function remainingWait(time) { 
 
\t \t const timeSinceLastCall = time - lastCallTime, 
 
\t \t \t timeSinceLastInvoke = time - lastInvokeTime, 
 
\t \t \t result = wait - timeSinceLastCall; 
 

 
\t \t return maxing ? Math.min(result, maxWait - timeSinceLastInvoke) : result; 
 
\t } 
 

 
\t function shouldInvoke(time) { 
 
\t \t const timeSinceLastCall = time - lastCallTime, 
 
\t \t \t timeSinceLastInvoke = time - lastInvokeTime; 
 

 
\t \t // Either this is the first call, activity has stopped and we're at the 
 
\t \t // trailing edge, the system time has gone backwards and we're treating 
 
\t \t // it as the trailing edge, or we've hit the `maxWait` limit. 
 
\t \t return (lastCallTime === undefined || (timeSinceLastCall >= wait) || 
 
\t \t \t (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); 
 
\t } 
 

 
\t function timerExpired() { 
 
\t \t const time = Date.now(); 
 
\t \t if (shouldInvoke(time)) { 
 
\t \t \t return trailingEdge(time); 
 
\t \t } 
 
\t \t // Restart the timer. 
 
\t \t timerId = setTimeout(timerExpired, remainingWait(time)); 
 
\t } 
 

 
\t function trailingEdge(time) { 
 
\t \t timerId = undefined; 
 

 
\t \t // Only invoke if we have `lastArgs` which means `func` has been 
 
\t \t // debounced at least once. 
 
\t \t if (trailing && lastArgs) { 
 
\t \t \t return invokeFunc(time); 
 
\t \t } 
 
\t \t lastArgs = lastThis = undefined; 
 
\t \t return result; 
 
\t } 
 

 
\t function cancel() { 
 
\t \t if (timerId !== undefined) { 
 
\t \t \t clearTimeout(timerId); 
 
\t \t } 
 
\t \t lastInvokeTime = 0; 
 
\t \t lastArgs = lastCallTime = lastThis = timerId = undefined; 
 
\t } 
 

 
\t function flush() { 
 
\t \t return timerId === undefined ? result : trailingEdge(Date.now()); 
 
\t } 
 

 
\t function debounced(...args) { 
 
\t \t const time = Date.now(), 
 
\t \t \t isInvoking = shouldInvoke(time); 
 

 
\t \t lastArgs = args; 
 
\t \t lastThis = this; 
 
\t \t lastCallTime = time; 
 

 
\t \t if (isInvoking) { 
 
\t \t \t if (timerId === undefined) { 
 
\t \t \t \t return leadingEdge(lastCallTime); 
 
\t \t \t } 
 
\t \t \t if (maxing) { 
 
\t \t \t \t // Handle invocations in a tight loop. 
 
\t \t \t \t timerId = setTimeout(timerExpired, wait); 
 
\t \t \t \t return invokeFunc(lastCallTime); 
 
\t \t \t } 
 
\t \t } 
 
\t \t if (timerId === undefined) { 
 
\t \t \t timerId = setTimeout(timerExpired, wait); 
 
\t \t } 
 
\t \t return result; 
 
\t } 
 
\t debounced.cancel = cancel; 
 
\t debounced.flush = flush; 
 
\t return debounced; 
 
} 
 

 
/** 
 
* Creates a throttled function that only invokes `func` at most once per 
 
* every `wait` milliseconds. The throttled function comes with a `cancel` 
 
* method to cancel delayed `func` invocations and a `flush` method to 
 
* immediately invoke them. Provide `options` to indicate whether `func` 
 
* should be invoked on the leading and/or trailing edge of the `wait` 
 
* timeout. The `func` is invoked with the last arguments provided to the 
 
* throttled function. Subsequent calls to the throttled function return the 
 
* result of the last `func` invocation. 
 
* 
 
* **Note:** If `leading` and `trailing` options are `true`, `func` is 
 
* invoked on the trailing edge of the timeout only if the throttled function 
 
* is invoked more than once during the `wait` timeout. 
 
* 
 
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred 
 
* until to the next tick, similar to `setTimeout` with a timeout of `0`. 
 
* 
 
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) 
 
* for details over the differences between `_.throttle` and `_.debounce`. 
 
*/ 
 
function throttle(func, wait, options) { 
 
\t if (!options) options = {}; 
 
\t let leading = true, 
 
\t \t trailing = true; 
 

 
\t leading = 'leading' in options ? !!options.leading : leading; 
 
\t trailing = 'trailing' in options ? !!options.trailing : trailing; 
 

 
\t return debounce(func, wait, { 
 
\t \t 'leading': leading, 
 
\t \t 'maxWait': wait, 
 
\t \t 'trailing': trailing 
 
\t }); 
 
} 
 

 

 
let counter=0; 
 

 
$('#slider').slider({ 
 
    min: 1, 
 
    max: 99, 
 
    orientation: 'vertical', 
 
    slide: throttle(function(event, ui) { 
 
    $(event.target).slider('option', 'value', ui.value); // making sure value is correct 
 
    console.log(ui.value); 
 
    }, 100) 
 
});
<link href="//code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css" rel="stylesheet" /> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script> 
 
<div id="slider"></div>

を含む

関連する問題