2015-04-17 1 views
2

У меня есть сеанс AJAX, который вызывается один раз на загрузку страницы и снова после щелчка. Во второй раз это не изменяет readistate, поэтому я решил протестировать его, поставив окно предупреждения в функцию. Появится окно предупреждения о загрузке страницы. Но по клику он не появляется - получите это, даже если сторона PHP выполняется. Еще более озадачивающим является то, что если я попытаюсь измерить readistate, он никогда не появится (не 0,1,2,3 или 4 - окно предупреждения даже не появится), и я не получу возвращаемый текст.Сессия AJAX называется дважды. Он не отображает предупреждение во второй раз

То, что я в конечном итоге пытаюсь достичь, это передать xmlhttp.responseText значение, подобное тому, которое оно делает при загрузке страницы. Что мне не хватает?

JavaScript:

function ajaxSession() 
 
{ 
 
alert(); 
 
xmlhttp = undefined; 
 
if (window.XMLHttpRequest) 
 
    {// code for IE7+, Firefox, Chrome, Opera, Safari 
 
    xmlhttp=new XMLHttpRequest(); 
 
    } 
 
else 
 
    {// code for IE6, IE5 
 
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); 
 
    } 
 
xmlhttp.onreadystatechange=function() 
 
    { 
 
    if (xmlhttp.readyState==4 && xmlhttp.status==200) 
 
    { 
 
\t z = xmlhttp.responseText; 
 
    } 
 
    } 
 
} 
 

 
function stateCheck() 
 
{ 
 
ajaxSession(); 
 
xmlhttp.open('POST', thisurl + '/favoritecheck.php',false); 
 
xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded'); 
 
xmlhttp.send("0=" + perform + "&1=" + thisplace + ",&2=" + thisusername); 
 
} 
 

 

 
function firstCheck() 
 
{ 
 
perform = 0; 
 
stateCheck(); 
 
\t if (z == 'found') 
 
\t { 
 
\t document.getElementById("favorite").src="http://www.********.com/images/favorite-on.png"; 
 
\t document.getElementById("favtext").innerHTML="This is a favorite!"; 
 
\t } 
 
\t if (z == 'nouser') 
 
\t { 
 
\t perform = 1; 
 
\t stateCheck(); 
 
\t } 
 
} 
 

 
function heartCheck() 
 
{ 
 
perform = 2; 
 
stateCheck(); 
 
\t if (z == 'added') 
 
\t { 
 
\t document.getElementById("favorite").src="http://www.********.com/images/favorite-on.png"; 
 
\t document.getElementById("favtext").innerHTML="This is a favorite!"; 
 
\t } 
 
\t if (z == 'subtracted') 
 
\t { 
 
\t document.getElementById("favorite").src="http://www.********.com/images/favorite-off.png"; 
 
\t document.getElementById("favtext").innerHTML="Add to your favorites."; 
 
\t } 
 
} 
 

 

 

 
if (loggedin == 1) 
 
{ 
 
document.writeln('<img id="favorite" style="cursor: pointer;" onclick="heartCheck()" src="http://www.********.com/images/favorite-off.png" alt="Favorite" />' 
 
+ '<br />' 
 
+ '<div id="favtext" style="color: #D20425;">' 
 
+ 'Add to your favorites.' 
 
+ '</div>'); 
 
firstCheck(); 
 
} else if (loggedin == 0) 
 
{ 
 
document.writeln('<img id="favorite" style="cursor: pointer;" src="http://www.********.com/images/favorite-off.png" alt="Favorite" />' 
 
+ '<br />' 
 
+ '<div id="favtext" style="color: #D20425;">' 
 
+ '<a style="color: #800000; font-weight: bold;" href="' + thisurl + '/wp-login.php">Log in</a> to add favorites.' 
 
+ '</div>'); 
 
}

PHP:

<?php 
 

 
include('connect.php'); 
 

 
$salt = "********"; 
 

 
$perform = $_POST[0]; 
 
$place = $_POST[1]; 
 
$user = $_POST[2]; 
 
$usercrypt = crypt(md5($user),$salt); 
 
$placeid = trim($place,","); 
 

 
function checkNow() 
 
{ 
 
global $usercrypt; 
 
global $place; 
 
global $conn; 
 
$urow = mysqli_query($conn, "SELECT Users.User FROM Users WHERE Users.User='" . $usercrypt . "';"); 
 
\t if (mysqli_num_rows($urow) > 0) 
 
\t { 
 
\t $favcheck = mysqli_query($conn, "SELECT Users.Favorites FROM Users WHERE Users.User='" . $usercrypt . "';"); 
 
\t $favcheck = mysqli_fetch_array($favcheck); 
 
\t $favcheck = $favcheck[0]; 
 
\t \t if (strpos($favcheck, $place) !== false) 
 
\t \t { 
 
\t \t $answer = 'found'; 
 
\t \t } 
 
\t \t else 
 
\t \t { 
 
\t \t $answer = 'notfound'; 
 
\t \t } 
 
\t } 
 
\t else 
 
\t { 
 
\t $answer = 'nouser'; 
 
\t } 
 
return array($answer,$favcheck); 
 
unset($answer); 
 
} 
 
\t 
 
if ($perform == "0") 
 
{ 
 
$sendback = checkNow(); 
 
echo $sendback[0]; 
 
unset($sendback); 
 
} 
 

 
if ($perform == "1") 
 
{ 
 
global $usercrypt; 
 
global $conn; 
 
mysqli_query($conn, "INSERT INTO Users (User) VALUES ('" . $usercrypt . "')"); 
 
} 
 

 
if ($perform == "2") 
 
{ 
 
$sendback = checkNow(); 
 
global $place; 
 
global $placeid; 
 
global $usercrypt; 
 
global $conn; 
 
$currentnum = mysqli_query($conn, "SELECT Places.Favorites FROM Places WHERE Places.PlaceID=" . $placeid); 
 
$currentnum = mysqli_fetch_array($currentnum); 
 
$currentnum = $currentnum[0]; 
 
\t if ($sendback[0] == 'found') 
 
\t { 
 
\t $currentnum--; 
 
\t $change = str_replace($place,'',$sendback[1]); 
 
\t mysqli_query($conn, "UPDATE Users SET Favorites='" . $change . "' WHERE User = '" . $usercrypt . "'"); 
 
\t mysqli_query($conn, "UPDATE Places SET Places.Favorites=" . $currentnum . " WHERE Places.PlaceID =" . $placeid); 
 
\t $answer = 'subtracted'; 
 
\t } 
 
\t if ($sendback[0] == 'notfound') 
 
\t { 
 
\t $currentnum++; 
 
\t $change = $sendback[1] . $place; 
 
\t mysqli_query($conn, "UPDATE Users SET Favorites='" . $change . "' WHERE User = '" . $usercrypt . "'"); 
 
\t mysqli_query($conn, "UPDATE Places SET Places.Favorites=" . $currentnum . " WHERE Places.PlaceID =" . $placeid); 
 
\t $answer = 'added'; 
 
\t } 
 
return $answer; 
 
unset($answer); 
 
} 
 

 
unset($_POST); 
 

 
?>

+0

Не могли бы вы также разместить свой HTML-код? –

+0

просто примечание: 'unset' после возврата не будет выполняться, а' global' должен использоваться только внутри функции. – jcubic

+0

HTML слишком длинный, чтобы добавить к сообщению. Это стандартная страница WordPress. Это содержание текста страницы: ' ' – Ryan

ответ

2

Значение z будет оценено до объект xmlhttp получает изменение readystate. Вам нужно поместить весь код, который имеет дело с возвращаемым значением, в функцию onreadystatechange, так как это единственная функция, которая, как гарантируется, будет вызвана после получения асинхронного ответа.

Вы могли бы сделать что-то вроде этого:

var xmlhttp = false; 
// The rest of your code, but remove the `onreadystatechange` assignment from ajaxSession() 
// ... 
// ... 
function heartCheck() { 
    perform = 2; 
    stateCheck(); 
    xmlhttp.onreadystatechange = function() { 
     z = xmlhttp.responseText; 
     if (z == 'added') 
     { 
     document.getElementById("favorite").src="http://www.********.com/images/favorite-on.png"; 
     document.getElementById("favtext").innerHTML="This is a favorite!"; 
     } 
     if (z == 'subtracted') 
     { 
     document.getElementById("favorite").src="http://www.********.com/images/favorite-off.png"; 
     document.getElementById("favtext").innerHTML="Add to your favorites."; 
     } 
    } 
} 

И вам нужно сделать обработчик, как, что для каждого времени вы хотите, чтобы оценить ответ AJAX.

Также было бы очень ясно объявить глобальные переменные в начале сценария, как я уже говорил выше, поскольку @jeroen упоминает, что это явно не требуется, но это хорошая практика и поможет вам отслеживать объем , Сложно предположить, что z определен только внутри функции xmlhttp.onreadystatechange, но вы используете ее во всем скрипте по всему миру. Итак, простой совет - поставить var z = '' в начале вашего JavaScript, чтобы ваши намерения были более четкими (как для вас самих, так и для других, которые могут просматривать ваш код :))

+0

Благодарим вас за исчерпывающий ответ. Это привело меня в ужас в течение 2 дней прямо сейчас. Мне нужно, чтобы оно объясняло то, как вы это делали. – Ryan

+0

Отличный ответ, хотя лично я постараюсь избежать целого глобального беспорядка :-) – jeroen

+0

Нет проблем. Удачи! Советы jeroen очень верны: лучше избегать таких структур в будущем, чтобы уклониться от путаных спагетти. :) –

1

Это немного беспорядок: Вы смешиваете асинхронным и синхр onous javascript таким образом, что вы никогда не узнаете, что есть и в каком состоянии вы находитесь. Кроме того, вы используете глобальные переменные javascript, которые вы перезагружаете и перезаписываете синхронно, пока вы используете их для своих асинхронных запросов.

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

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

+1

Спасибо, что указали на недостатки, которые я просто не видел. Я самоучка (явная!), И мне действительно нужна была какая-то внешняя перспектива. – Ryan

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