суббота, 4 октября 2014 г.

Отложенное выполнение

Для отложенного выполнения кода используются следующие системные функции:

setTimeout(callback, delay); 
setInterval(callback, delay);

Первая функция вызывает функцию callback разово через интервал времени не меньший delay. До того времени система продолжает выполнять имеющийся код (для заморозки процесса выполнения нужно использовать функцию sleep()).

Вторая функция выполняет callback с периодичностью delay. Т.к. в разных браузерах существует значительный разброс между временем выполнения setInterval() рекомендуется использовать следующий шаблон для его замены:

/**

* @param {Function} callback Функция, вызываемая по окончании работы.

*/
function foo(callback) {
// Инициализируем переменные
(function inner() {
// Выполняем действия
if (/* больше ничего делать не надо */) {
callback();
} else {
setTimeout(inner, 500);
}
})();
}


setTimeout возвращает идентификатор таймера, который можно отменить, если потребность в вызове функции отпала с помощью функции clearTimeout(timerId).


Т.к. код отложенного вызова может быть довольно громоздким, можно использовать следующее расширение прототипа функции:

/** * Вызывает функцию указанное количество миллисекунд в контексте ctx 
* с аргументами args. * @param {Number} millis * @param {Object} ctx * @param {Array} args * @return {Number} Идентификатор таймаута. */ Function.prototype.defer = function(timeout, ctx, args) { var that = this; return setTimeout(function() { that.apply(ctx, args || []); }, timeout); };

Теперь отложенные вызовы значительно упростятся:

foo.defer(1000, this, [1, 2])

Иногда возникает необходимость вызывать какую-либо функцию только если в течение некоторого времени не происходит пользовательской активности. Для этого используется такой шаблон:

/** * Возвращает функцию, вызывающую исходную с задержкой delay в контексте ctx. * Если во время задержки функция была вызвана еще раз, то предыдующий вызов * отменяется, а таймер обновляется. Таким образом из нескольких вызовов, * совершающихся чаще, чем delay, реально будет вызван только последний. * @param {Number} delay * @param {Object} ctx * @return {Function} */ Function.prototype.debounce = function(delay, ctx) { var fn = this, timer; return function() { var args = arguments, that = this; clearTimeout(timer); timer = setTimeout(function() { fn.apply(ctx || that, args); }, delay); }; };

Теперь возможен следующий вариант. Пусть функция suggest() выводит подсказки к пользовательскому вводу, для чего производит запросы к серверу. Подсказки будем выводить только после того как пользователь не печатает в течение какого-то времени:

document.getElementById('text').onkeypress = suggest.debounce(500);

Комментариев нет :

Отправить комментарий