#javascript
Вопрос:
Например, у меня есть анимация, я воспроизводю ее с помощью setInterval. Когда происходит событие, которое я ранее установил на веб-странице, я хочу, чтобы была запущена функция обратного вызова для вызова clearInterval. Любопытно, есть ли способ настроить такую функцию обратного вызова для всех событий, существующих на веб-странице. Потому что в противном случае мне придется просмотреть каждое событие, которое я установил ранее. В виде кода меня интересует что-то подобное:
const i = setInterval(function() { //do something }, 50); AdditionalCallbackForEveryEventSet(function() { clearInterval(i); });
Ответ №1:
У меня был аналогичный опыт, но я хотел очистить всех слушателей, когда пользовательский компонент был удален из DOM (следовательно, я использовал .call()
). Это может быть немного слишком сложно для вас, но я хочу отметить, что вам нужно создать функциональность, которую вам нужно использовать, вместо того, чтобы напрямую устанавливать интервал/прослушиватели setInterval/addEventListener
.
Некоторые Примеры
Добавить слушателя
FXListenerBehavior.setListener.call(window, 'aKeyToDiffentiate', functionName);
Удалить прослушиватель
FXListenerBehavior.clearListener.call(window, 'aKeyToDiffentiate', functionName);
Добавить интервал
const TIME_IN_MILLIS = 2000;
FXListenerBehavior.setInterval.call(window, 'aKeyToDiffentiate', functionName, TIME_IN_MILLIS);
Удалите все интервалы и прослушиватели
FXListenerBehavior.clearAllIntervals.call(window);
Выведите все прослушиватели и интервалы
Приятно при отладке.
FXListenerBehavior.printAll.call(window);
Удалите всех слушателей и интервалы
FXListenerBehavior.clearAll.call(window);
FXListenerBehavior = { /* === SET AND UPDATE === */ /** * @description sets a listener * @param {String} name any descriptive name * @param {function} method the function to be run with the listener * @param {setOnElement} Boolean if the listener should be set on the element or default to window * @return {Boolean} true if set, false if listener already exist */ setListener: function(name, method, setOnElement) { if (FXListenerBehavior._alreadyExist.call(this, name)) { var elementName = FXListenerBehavior._getElementName.call(this); console.warn(elementName '"' name '" already exist. Use updateListener() if you're unsure if the listener exists'); return false; } return FXListenerBehavior._setListener.call(this, name, method, setOnElement); }, /** * @description sets an interval * @param {String} name any descriptive name * @param {function} method the method to be repeated * @param {Integer} time repeats method after this many milliseconds * @return {Boolean} true if set, false if listener already exist */ setInterval: function(name, method, time) { if (FXListenerBehavior._alreadyExist.call(this, name)) { var elementName = FXListenerBehavior._getElementName.call(this); console.warn(elementName '"' name '" already exist. Use updateInterval() if you're unsure if the interval exists'); return false; } return FXListenerBehavior._setInterval.call(this, name, method, time); }, /** * @description replaces a listener or interval, or creates one if it doesn't exist * @param {String} name any descriptive name * @param {function} method the method to be run * @param {Integer} time repeats method after this many milliseconds (only for intervals) * @return {Boolean} always true */ update: function(name, method, time) { if (time gt; 0) { return FXListenerBehavior.updateInterval.call(this, name, method, time); } else { var setOnElement = time; return FXListenerBehavior.updateListener.call(this, name, method, setOnElement); } }, updateListener: function(name, method, setOnElement) { FXListenerBehavior.clearListener.call(this, name); return FXListenerBehavior._setListener.call(this, name, method, setOnElement); }, updateInterval: function(name, method, time) { FXListenerBehavior.clearInterval.call(this, name); return FXListenerBehavior._setInterval.call(this, name, method, time); }, _setListener: function(name, method, setOnElement) { if (name == undefined || method == undefined) { traceDebug('name or method is undefined', name, method) return } this._listenersAndIntervals[name] = method; if (setOnElement) { this.addEventListener(name, method, { 'passive': true }); } else { window.addEventListener(name, method, { 'passive': true }); } return true; }, _setInterval: function(name, method, time) { if (name == undefined || method == undefined) { traceDebug('name or method is undefined', name, method) return } var intervalId = setInterval(method, time); this._listenersAndIntervals[name] = intervalId; return true; }, _alreadyExist: function(name) { if (typeof this._listenersAndIntervals === 'undefined') { this._listenersAndIntervals = {}; } if (this._listenersAndIntervals[name]) { return true; } return false; }, /* === GET AND PRINT === */ getAll: function() { return Object.keys(this._listenersAndIntervals); }, printAll: function() { if (this._listenersAndIntervals) { var isPolymer2Element = this.is == 'function'; let elementName = (isPolymer2Element) ? this.is() : this.is; console.info("All listeners and intervals for " elementName ":n" JSON.stringify(Object.keys(this._listenersAndIntervals))); } }, /* === CLEAR === */ /** * @description clears a listener * @param {String} name any descriptive name, previously set with setListener */ clearListener: function(name) { if (FXListenerBehavior._alreadyExist.call(this, name)) { window.removeEventListener(name, this._listenersAndIntervals[name]) delete this._listenersAndIntervals[name]; } }, /** * @description clears an interval * @param {String} name any descriptive name, previously set with setInterval */ clearInterval: function(name) { if (FXListenerBehavior._alreadyExist.call(this, name)) { clearInterval(this._listenersAndIntervals[name]); delete this._listenersAndIntervals[name]; } }, clearAllListeners: function() { FXListenerBehavior._clear.call(this, 'listener'); }, clearAllIntervals: function() { FXListenerBehavior._clear.call(this, 'interval'); }, clearAll: function(print) { if (print) { FXListenerBehavior.printAll.call(this) } FXListenerBehavior._clear.call(this); if (print) { FXListenerBehavior.printAll.call(this) } }, _clear: function(listenerOrInterval) { if (typeof this._listenersAndIntervals === 'object') { var keys = Object.keys(this._listenersAndIntervals); for (var i = keys.length - 1; i gt;= 0; i--) { if (typeof this._listenersAndIntervals[keys[i]] === 'function' amp;amp; listenerOrInterval !== 'interval') { FXListenerBehavior.clearListener.call(this, keys[i]); } else if (typeof this._listenersAndIntervals[keys[i]] === 'number' amp;amp; listenerOrInterval !== 'listener') { FXListenerBehavior.clearInterval.call(this, keys[i]); } else { var elementName = FXListenerBehavior._getElementName.call(this); console.warn(elementName keys[i] ' is not a ' (listenerOrInterval || 'listener')); } } } }, _getElementName: function() { var elementName = this.is || this.tagName || this.nodeName; if (!elementName) { traceDebug('FXListenerBehavior lacks element information'); } return (this) ? elementName ': ' : ''; } }