setTimeout не работает

Я хочу загрузить файл OWL перед выполнением других сценариев (визуализации). Для этого я пробовал все от

$(document).ready

to

function visualize (file) {
if (!file)
    {setTimeout(visualize(file), 2000)}
else
    {jQuery(function($){visFeaturePool.init(file)})}}

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

Кто-нибудь знает, что я делаю неправильно? Спасибо!


person JasperTack    schedule 04.12.2011    source источник
comment
setTimeout не имеет проблемы, вы не можете передавать параметры функции, которую вы хотите, чтобы setTimeout выполнила.   -  person Jonathon    schedule 04.12.2011
comment
Дубликат Вызов функций с помощью setTimeout()   -  person Heretic Monkey    schedule 15.06.2020


Ответы (4)


Вместо

// #1
setTimeout(visualize(file), 2000);

ты хочешь

// #2
setTimeout(function() {
    visualize(file);
}, 2000);

или в современных браузерах вы можете указать аргументы для передачи функции после задержки:

// #3
setTimeout(visualize, 2000, file);

Эти трое объяснили:

  1. (Как упоминает SLaks) Это вызывает visualize немедленно, а затем передает возвращаемое значение в setTimeout (и, поскольку visualize вызывает сам себя, он продолжает вызывать себя рекурсивно, и в итоге вы получаете переполнение стека ошибка).
  2. Это передает ссылку на функцию в setTimeout, которая при вызове вызовет visualize и передаст ей аргумент file (с его значением, как оно тогда). Функция, которую мы передаем в setTimeout, будет иметь доступ к аргументу file, даже если ваш код запустился и вернулся, потому что эта функция является замыканием над контекстом, в котором она была создана, включая file . Подробнее: Замыкания не сложны< /a> Обратите внимание, что значение переменной file считывается с момента срабатывания таймера, а не с момента его настройки.
  3. Это передает ссылку на функцию visualize в setTimeout (обратите внимание, что после нее нет () или (file)), а также передает file в setTimeout, используя ее значение на момент настройки вызова. Позже, в современных средах, setTimeout передаст это функции при ее последующем вызове.

Между #2 и #3 есть важное различие: в #2, если file изменяется между вызовом setTimeout и истечением времени таймера, visualize увидит новое значение file. Однако с № 3 этого не произойдет. У обоих есть свое применение. Вот пример этой разницы:

let file = 1;

// #2, using "file" when the timer fires, not when you set it up
setTimeout(function() { visualize(file); }, 2000); // Shows 2

// #3, using "file" right away when setting up the timer
setTimeout(visualize, 2000, file); // Shows 1

file = 2;

function visualize(value) {
    console.log(value);
}

Если вам нужно поведение #3 для немедленного чтения file (а не ожидания срабатывания таймера) в среде, которая не поддерживает дополнительные аргументы для setTimeout, вы можете сделать это:

// #4 (for environments that don't support #3)
setTimeout(visualize.bind(null, file), 2000);
person T.J. Crowder    schedule 04.12.2011
comment
Большое спасибо за помощь, почему-то все настаивают на использовании setTimeout(function(file), миллисекунды); который вообще не работает, это спасло мой день. - person Mostafa; 09.07.2020

setTimeout(visualize(file), 2000) вызывает visualize немедленно и передает результат setTimeout, как и любой другой вызов функции.

person SLaks    schedule 04.12.2011

Попробуй это:

function visualize (file) {
  if (!file)
    {setTimeout(function(){visualize(file);}, 2000)}
  else
    {jQuery(function($){visFeaturePool.init(file)})}}

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

person Sebastián Grignoli    schedule 04.12.2011

setTimeout(visualize, 2000, file);

также будет работать.

person neonguru    schedule 03.11.2017