Бывает нужно подписаться на какое-то событие, но нет уверенности, что оно вообще может наступить. Можно условиться о неком интервале, в течение которого мы ожидаем это событие.
/**
* @param {Function} fn function which needs to be called only once
* @param {Number} timeout for external call
* @param {Object} [context]
* @returns {Function}
*/
function withTimeout(fn, timeout, context) {
var timerId, state = true;
function cb() {
if (timerId) {
clearTimeout(timerId);
timerId = null;
}
if (state) {
state = false;
fn.apply(context || window, arguments);
}
}
timerId = setTimeout(cb, timeout);
return cb;
}
С использованием промисов код получился бы чуть короче, но потребовал бы внешнюю зависимость в виде jQuery или другой библиотеки, реализующей промисы.
Коментарии к заметке
такие штуки называются debounce, вот например как это сделано в lodash. также есть ф-ция throttle которая гарантирует что с определенным интервалом функция всётаки будет вызываться. throttle может пригодиться в случае когда допустим мы повесили такого рода функцию на ресайз окна чтобы дождаться когда юзер перестанет ресайзить окно, а юзер попался редкий аутист и окно ресайзить не перестаёт, так вот указав throttle в 1000мс, один раз в секунду функция выполняться все-таки будет.