2011-11-19 2 views
15

Я пытаюсь обмотать голову вокруг setTimeout, но я не могу заставить его работать правильно.setTimeout delay не работает

Я настроил пример здесь: http://jsfiddle.net/timkl/Fca2n/

Я хочу текст отсчета после анкера щелкнул - но мой setTimeout кажется, стрелять в то же время, несмотря на то, что я установить задержку в 1 сек.

Это мой HTML:

<a href="#">Click me!</a> 

<span id="target"></span> 

Это мой JS:

$(document).ready(function() { 


function foo(){ 

    writeNumber = $("#target"); 

    setTimeout(writeNumber.html("1"),1000); 
    setTimeout(writeNumber.html("2"),1000); 
    setTimeout(writeNumber.html("3"),1000); 
    }; 

$('a').click(function() { 
foo(); 
}); 

}); 

Любой намек на то, что я могу делать неправильно высоко ценится :)

ответ

37

setTimeout принимает функцию в качестве аргумента. Вы выполняете функцию и передаете результат в setTimeout (поэтому функция выполняется сразу). Вы можете использовать анонимные функции, например:

setTimeout(function() { 
    writeNumber.html("1"); 
}, 1000); 

Обратите внимание, что то же самое относится и к setInterval.

+0

Thx за помощь мне! :) Я обновил свой jsfiddle: http://jsfiddle.net/timkl/cRDQh/ Я все равно получаю тот же результат, срабатывает setTimeouts одновременно. – timkl

+1

Нет проблем :) Если вы не хотите, чтобы они срабатывали одновременно, измените длину таймаута. Например, 1000 мс для первого тайм-аута, 2000 мс для второго и т. Д. –

+0

То же самое верно не только для 'setTimeout' и' setInterval', но для каждого случая вы должны пройти обратный вызов в качестве одного из параметров. – Tadeck

2

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

setTimeout(function() { writeNumber.html("1"); },1000); 

Кроме того, вы хотите использовать другое значение задержки для каждого из них, так что таймеры не истекает в то же время. См. Обновленную скрипту: http://jsfiddle.net/RqCqM/

1

Просто используйте setInterval(). Here, что я придумал. Вот ваш новый JavaScript:

function foo(){ 
    writeNumber = $("#target"); 
    number  = 0; 
    writeNumber.html(number); 
    setInterval(function(){ 
     number = number+1; 
     writeNumber.html(number); 
    },1000); 
    }; 
$('a').click(function() { 
foo(); 
}); 
5

Вы должны обернуть ваши заявления в анонимных функций, а также шататься ваши тайминги -

setTimeout(function(){writeNumber.html("1")},1000); 
setTimeout(function(){writeNumber.html("2")},2000); 
setTimeout(function(){writeNumber.html("3")},3000); 

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

Demo - http://jsfiddle.net/JSe3H/1/

+0

+1 Хорошая точка - вы указали не только способ передачи обратного вызова, но и когда он выполняется. – Tadeck

1

Вы должны карапуз Используйте функции, которая будет вызвана после того, как будет принят тайм-аут; вы также можете использовать анонимную функцию, тогда ваша функция foo будет выглядеть так:

function foo(){ 

writeNumber = $("#target"); 

setTimeout(function() { writeNumber.html("1"); },1000); 
setTimeout(function() { writeNumber.html("2"); },1000); 
setTimeout(function() { writeNumber.html("3"); },1000); 

}; 
0

Я приземлился на этот вопрос. Ответ был дан адекватно, и я думаю, что использование setInterval в качестве предлагаемого @Purag, вероятно, является лучшим подходом для получения желаемого функционального поведения. Однако исходный код не учитывал асинхронное поведение JavaScript. Это часто встречающаяся ошибка, которую я сделал больше, чем когда-либо :).

Так как примечание стороны, я хотел бы дать еще одно возможное решение для этого, которое имитирует первую попытку, но на этот раз ДЕЛАЕТ считают Asynchronousity в JavaScript:

setTimeout(function() { 
    writeNumber.html("1"); 
    setTimeout(function() { 
     writeNumber.html("1"); 
     setTimeout(function() { 
      writeNumber.html("1"); 
     }, 1000); 
    }, 1000); 
}, 1000); 

Сейчас конечно это явно ужасный код!

Я дал рабочий JSFiddle в my own SO question. Этот код иллюстрирует так называемую пирамиду doom. И это можно смягчить, используя обещания JavaScript, как показано в ответах на мой вопрос. Она занимает определенную работу, чтобы написать версию WriteNumber(), которая использует посылы, но затем код можно переписать somehting как:

2

Существует положение, чтобы передать аргументы функции. В вашем случае, вы можете сделать это

setTimeout(writeNumber.html,1000,1); 
setTimeout(writeNumber.html,1000,2); 
setTimeout(writeNumber.html,1000,3); 

третий аргумент функции SetTimeout будет перейти к функции writeNumber.html

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