2012-01-11 3 views
1

Я не знаю много о JavaScript, вот код, у меня есть:JavaScript - Функция, возвращающая дважды

<script language="JavaScript"> 
var x = 10 

function startClock() { 
    if (x !== ' ') { 
     x = x - 1 
     document.frm.clock.value = x 
     setTimeout("startClock()", 1000) 
    } 
    if (x == 0) { 
     x = ' '; 
     document.frm.clock.value = x; 
     success.location.href = "success.php"; 
    } 
} 
</script> 
<body onLoad(startClock);> 

затрагиваемой IFrame:

<input name="clock" size="3" readonly="readonly" 

<iframe name="success" src="blank.htm"></iframe> 

, когда таймер отсчитывает, Success.php загружается дважды. Я знаю это потому, что 1.) Он дважды вставляет данные в мою БД, 2.) Я могу увидеть символ загрузки на вкладке, перезагружая секунду.

Когда я изменить функцию на что-то вроде:

<script language="JavaScript"> 

var x = 10 
var y = 1 

function startClock() { 
    if (x !== 'Fin') { 
     x = x - y 
     document.frm.clock.value = x 
     setTimeout("startClock()", 1000) 
    } 
    if (x == 0) { 
     x = 'Fin'; 
     document.frm.clock.value = x; 
     success.location.href = "success.php"; 
    } 
} 

</script> 

... страница загружается только один раз.

Может ли кто-нибудь сказать мне, что здесь происходит? Я также попытался с помощью «0» вместо «» и получил тот же двойное исполнение ...

+0

Изменение ваших вторых 'if' и' else if' может решить вашу проблему. – Ivan

+0

* «Он дважды вставляет данные в мою БД». * Тогда вам может понадобиться исправить вашу страницу сервера. Операции 'GET' должны быть [idempotent] (http://en.wikipedia.org/wiki/Idempotence) (извините, не мое слово). Для операций, которые * изменяют * вещи, используйте 'POST' или один из других глаголов. (Исключение, на мой взгляд, является «посещением» данных.) –

+0

В первой версии вашего вопроса использовалось значение флага '' ''. В текущей версии используется «Fin». Что он? О, подождите, он снова вернется к '' "'. –

ответ

0

Изменить это:

if (x == 0) { // note this is now first 
    x = ' '; 
    document.frm.clock.value = x; 
    success.location.href = "success.php"; 
} else if (x !== ' ') { // note the else/if 
    x = x - 1; 
    document.frm.clock.value = x; 
    setTimeout("startClock()", 1000) 
} 

В противном случае, когда х 1, тайм-аут для startClock() будет быть установленным, и местоположение будет загружено. Затем погаснет тайм-аут, снова загрузив страницу (начиная с x = ' ' и ' ' == 0 возвращает true).

Это, вероятно, лучше практика, чтобы сказать:

if (x === 0) { // note the === 
    x = ' '; 
    document.frm.clock.value = x; 
    success.location.href = "success.php"; 
} else if (x !== ' ') { 
    x = x - 1; 
    document.frm.clock.value = x; 
    setTimeout("startClock()", 1000) 
} 

Потому что вам не нужно преобразование истины, что == делает для вас.


Ваш пример с 'Fin' вместо ' ' работал, потому что на startClock() вызова после того, как было загружено место, x был 'Fin' и ('Fin' == 0) ложно.

+0

Просто попробовал, по какой-то причине инструкция else if не запускается ... Таймер продолжается до отрицательного значения после того, как он достигает нуля. Это как если бы x никогда не равнялось 0 ??? – user1142872

+0

Ах. Логика ошибочна. Я обновлю ответ, но я бы рекомендовал версию @Murray McDonald's. Он чище. Я дал ему преимущество - и если вы найдете его решение полезным тоже, вам тоже нужно :) (также приветствуем переполнение стека) –

+0

Теперь его нужно исправить. –

0

Первый пара вещей. В вашем примере существует несколько «неаккуратных» методов кодирования (например, точки с запятой отсутствуют). Хотя код может работать, он может улучшиться с помощью некоторой справки jslint.

Итак, посмотрите на случай, когда x = 1. Вы уменьшаете x так теперь x = 0. Затем вы вызываете setTimeout, который будет ждать 1 секунду, а затем вызовите ваш метод с именем startClock. Однако setTimeout не блокирует выполнение. Итак, сразу после вызова setTimeout с x = 0, код под ним выполняется, когда вы устанавливаете x в '' (и загружаете свою страницу). Теперь через секунду после запуска этого кода ваш метод снова вызван из-за срабатывания таймера. Поскольку x теперь '', верхний блок пропускается, и вы попадаете в блок x == 0 второй раз.

1

В JavaScript есть два операторы сравнения:

«==» - означает, что равно

«===» означает «точно равно» - это означает, что значение и TYPE должен быть таким же

Я подозреваю (хотя я и не хочу проверять теорию), что если вы используете «===», а не «==» в своем исходном коде, вы обнаружите, что он работает так, как вы планировали.Тем не менее, есть ряд вещей, которые нуждаются в исправлении: 1) вы несовместимы с использованием «;», 2) код должен быть структурирован, чтобы гарантировать, что на любой заданной итерации он может только «перезапустить» таймер или запустить процесс и НИКОГДА оба. Вот более чистая версия:

<script language="JavaScript"> 
    // 10 iterations at 1 second intervals 
    var x = 10; 

    function startClock() { 
    document.frm.clock.value = --x; 
    if (x <= 0) { 
     document.frm.clock.value = x; 
     success.location.href = "success.php"; 
    } else { 
     setTimeout("startClock()", 1000); 
    } 
    } // startClock 
</script> 
<body onLoad(startClock);> 
+0

+1 Хороший ответ. Я думаю, что второй 'document.frm.clock.value = x;' лишний. Или, может быть, вы имели в виду '= '';'? –

+0

Да, совершенно лишний - просто упустил из виду, когда я двигался вокруг - в PHP 0 == '' TRUE, но 0 === '' FALSE - я знаю, что приведенный выше код использует '' (single пустой, а не пустая строка), но тот факт, что, когда он изменил свое «дозорное» значение от этого до «Fin», он работал очень сильно, заставляя меня думать, что это происходит –

+0

Спасибо за очистку «==» и «== = ', что-то новое. Спасибо за чистый код, отлично работает! – user1142872

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