JavaScript вернет это после того, как метод элемента html запустит setTimeout
Итак, у меня есть этот код, добавление метода (из того, что я понимаю) в прототип HTML-элемента:
HTMLElement.prototype.fadeIn = function( seconds ) {
var self = this;
var miliseconds = seconds * 1000;
var hold = this.style.transition;
this.style.transition = "opacity " + seconds + "s ease";
this.style.opacity = 1;
setTimeout(
function () {
self.style.transition = hold;
return self;
},
miliseconds);
};
Мое намерение состоит в том, чтобы в конце тайм-аута функция возвращала экземпляр HTMLElement, чтобы я мог связать функцию fadeIn с другой.
Однако это не так, и, делая console.log к тому, что он возвращает, он говорит, что он не определен. Может кто-нибудь дать совет, как я могу это сделать?
2 ответа
setTimeout()
это асинхронная операция Это не "приостанавливает" выполнение вашего fadeIn()
функция. Ваш .fadeIn()
Метод немедленно возвращается, а затем происходит операция таймера.
возврате self
от setTimeout()
обратный вызов не делает ничего полезного. Просто возвращается self
во внутренние недра подсистемы таймера, где она покорно игнорируется.
Вы можете поддержать цепочку из вашего .fadeIn()
операция, просто добавив return this;
до конца вашего метода:
HTMLElement.prototype.fadeIn = function( seconds ) {
var self = this;
var miliseconds = seconds * 1000;
var hold = this.style.transition;
this.style.transition = "opacity " + seconds + "s ease";
this.style.opacity = 1;
setTimeout(
function () {
self.style.transition = hold;
}, miliseconds);
return this;
};
Но это не скажет вам ничего о том, когда операция замирания фактически завершена. Если вы хотите это знать, вам нужно будет спроектировать что-то еще в вашем методе (обратный вызов, обещание или очередь) для поддержки цепочки анимации.
Если вы пытаетесь создать анимацию, как это делает jQuery, вы можете сделать это:
obj.fadeIn(5).fadeOut(5);
и две анимации будут происходить последовательно, тогда потребуется более сложная система. jQuery использует очередь анимации, где анимация не обязательно выполняется сразу, а скорее добавляется в очередь, специфичную для этого конкретного объекта DOM. Всякий раз, когда анимация для этого конкретного объекта завершается, он смотрит в свою очередь, чтобы увидеть, есть ли еще одна анимация, ожидающая того же объекта. Если это так, он запускает эту анимацию.
Кроме того, если вы используете анимацию CSS3 и вам нужно знать, когда анимация завершена, вам нужно будет зарегистрироваться для события transitionend объекта.
Вы не можете вернуть что-то после истечения времени ожидания, потому что поток гераклита перешел: куда вы тоже собираетесь вернуться?
Один простой способ связывания функций с задержками - передать их в:
HTMLElement.prototype.fadeIn = function(seconds, continueWith) {
var self = this;
var miliseconds = seconds * 1000;
var hold = this.style.transition;
this.style.transition = "opacity " + seconds + "s ease";
this.style.opacity = 1;
setTimeout(
function () {
self.style.transition = hold;
if(continueWith)
continueWith();
},
miliseconds);
};
Вы могли бы назвать это с el.fadeIn(1.5, function(){el.fadeOut(2);})
; а потом fadeOut
будет вызван после fadeIn
было завершено.
Вы также можете вернуть объект обещания:
function createTimeoutPromise(timeOut)
{
var promise =
{
toRun: null,
continueWith: function(func)
{
this.toRun = func;
}
}
setTimeout(function()
{
if(promise.toRun)
promise.toRun();
}, timeOut);
return promise;
}
HTMLElement.prototype.fadeIn = function(seconds)
{
var self = this;
var miliseconds = seconds * 1000;
var hold = this.style.transition;
this.style.transition = "opacity " + seconds + "s ease";
this.style.opacity = 1;
return createTimeoutPromise(miliseconds);
};
Вы можете позвонить с помощью Вы можете позвонить с помощью el.fadeIn(1.5).continueWith(function(){el.fadeOut(2);});
который может быть более хорошим стилем цепочки.
Обратите внимание, что в обоих случаях мы проверяем на отсутствие функции для продолжения, чтобы конец цепочки не вызывал ошибку.