2015-05-26 3 views
10

Например, есть переменная называется animationComplete (из библиотеки третьей стороной) и функция называется happenAfterAnimation:Предпочтительный способ опроса локального значения в Javascript?

Простое решение выглядит следующим образом:

while(!animationComplete) { 
    // Do nothing 
} 
happenAfterAnimation() 

или более сложное решение, как это :

function tryHappenAfterAnimation() { 
    if(animationComplete) { 
    happenAfterAnimation() 
    } else { 
    setTimeout(tryHappenAfterAnimation, 100) 
    } 

} 
setTimeout(tryHappenAfterAnimation, 100) 

Первое решение может иметь некоторые накладные расходы, а второе решение выглядит немного грязным.

Как future/promise не доступен в текущей версии Javascript, что способ может быть немного излишним здесь .. мне было просто интересно, есть ли это элегантный и легкий способ для данной ситуации ..

Кто-нибудь есть идеи о лучшем способе борьбы с этим? Благодаря!

+0

Попробуйте пользовательское событие или паб/sub. Вероятно, это идеальный вариант в этой ситуации. – colecmc

+0

«Поскольку будущее/обещание недоступно в текущей версии Javascript ...» Задача языка не предоставлять фьючерсы/обещания/события для его библиотек. Это задача библиотек. –

ответ

3

Первый подход не будет работать вообще. Он будет блокировать поток навсегда.

Отсутствие встроенной поддержки обещаний на самом деле не является оправданием, чтобы не использовать обещания. Если ваша библиотека дает вам способ, способный к событию/обратному вызову, ждать результатов (и я был бы удивлен, если бы это не так), тогда вы должны использовать событие или обещания.

Если нет, и опрос переменной на самом деле является вашим единственным вариантом, я бы сказал, что ваш второй подход - это почти единственный вариант.

2

Краткое описание - Ваш первый метод не будет работать (это будет просто бесконечный цикл), и механизм опроса (хотя его можно заставить работать) никогда не является «предпочтительным» выбором.

Javascript является однопоточным (за некоторыми исключениями, такими как webWorkers, но они здесь не применяются), так как пока цикл while работает, никакая другая JS не может запускаться, что может изменить значение animationComplete, чтобы вы могли бесконечный цикл, который никогда не будет завершен (в конце концов браузер будет жаловаться на то, что поток JS не завершил и предоставил пользователю возможность остановить скрипт).

Правильный способ узнать, когда завершена анимация, - использовать обратный вызов для завершения анимации. Если вы используете jQuery, то все анимации jQuery имеют обратный вызов завершения, который вы можете передать, и он будет вызван, когда анимация будет выполнена. Затем вы помещаете код, который вы хотите выполнить после анимации в этой функции обратного вызова.

Если вы используете анимацию CSS3, вы можете зарегистрировать обработчик событий для события transitionend и получить обратный вызов таким образом, когда анимация будет завершена.

Если вы хотите опросить значение переменной, то использование таймера для опроса будет подходящим выбором, так как это позволяет запускать другой код, который может фактически изменить переменную.

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


Для нас, чтобы обеспечить более подробные рекомендации, мы должны были бы знать больше о коде анимации и то, что вы пытаетесь сделать. Как я уже говорил, все анимации jQuery обеспечивают обе возможности и поддержку обратного вызова для уведомления о завершении (вы отметили вопрос jQuery, почему я упоминаю об этом).

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

1

Вот подход, основанный на Promises. Следующее выполняет периодический опрос наряду с таймаутом.

var Promise = require('bluebird'); 

/** 
* Periodically poll a signal function until either it returns true or a timeout is reached. 
* 
* @param signal function that returns true when the polled operation is complete 
* @param interval time interval between polls in milliseconds 
* @param timeout period of time before giving up on polling 
* @returns true if the signal function returned true, false if the operation timed out 
*/ 
function poll(signal, interval, timeout) { 
    function pollRecursive() { 
     return signal() ? Promise.resolve(true) : Promise.delay(interval).then(pollRecursive); 
    } 

    return pollRecursive() 
     .cancellable() 
     .timeout(timeout) 
     .catch(Promise.TimeoutError, Promise.CancellationError,function() { 
      return false; 
     }); 
} 

Вы называете это так.

poll(animationComplete, pollingInterval, timeout) 
    .then(function(complete) { 
     if (complete) 
      happenAfterAnimation(); 
    } 
); 

См. Javascript polling with promises.

Смежные вопросы