【问题标题】:AJAX Session called twice. It doesn't show an alert the second timeAJAX 会话调用了两次。第二次没有显示警报
【发布时间】:2015-06-24 08:39:38
【问题描述】:

我有一个 AJAX 会话,它在页面加载时调用一次,然后在单击后再次调用。它第二次没有改变 readystate,所以我决定通过在函数中放置一个警告框来测试它。警告框显示在页面加载上。但是在点击它并没有出现 - 得到这个 - 即使 PHP 端执行。更令人费解的是,如果我尝试测量 readystate,它永远不会出现(不是 0、1、2、3 或 4 - 甚至不会出现警告框),而且我没有得到返回文本。

我最终想要实现的是让 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)
    {
	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();
	if (z == 'found')
	{
	document.getElementById("favorite").src="http://www.********.com/images/favorite-on.png";
	document.getElementById("favtext").innerHTML="This is a favorite!";
	}
	if ( z == 'nouser')
	{
	perform = 1;
	stateCheck();
	}
}

function heartCheck()
{
perform = 2;
stateCheck();
	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.";
	}
}



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 . "';");
	if (mysqli_num_rows($urow) > 0)
	{
	$favcheck = mysqli_query($conn, "SELECT Users.Favorites FROM Users WHERE Users.User='" . $usercrypt . "';");
	$favcheck = mysqli_fetch_array($favcheck);
	$favcheck = $favcheck[0];
		if (strpos($favcheck, $place) !== false)
		{
		$answer = 'found';
		}
		else
		{
		$answer = 'notfound';
		}
	}
	else
	{
	$answer = 'nouser';
	}
return array($answer,$favcheck);
unset($answer);
}
	
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];
	if ($sendback[0] == 'found')
	{
	$currentnum--;
	$change = str_replace($place,'',$sendback[1]);
	mysqli_query($conn, "UPDATE Users SET Favorites='" . $change . "' WHERE User = '" . $usercrypt . "'");
	mysqli_query($conn, "UPDATE Places SET Places.Favorites=" . $currentnum . " WHERE Places.PlaceID =" . $placeid);
	$answer = 'subtracted';
	}
	if ($sendback[0] == 'notfound')
	{
	$currentnum++;
	$change = $sendback[1] . $place;
	mysqli_query($conn, "UPDATE Users SET Favorites='" . $change . "' WHERE User = '" . $usercrypt . "'");
	mysqli_query($conn, "UPDATE Places SET Places.Favorites=" . $currentnum . " WHERE Places.PlaceID =" . $placeid);
	$answer = 'added';
	}
return $answer;
unset($answer);
}

unset($_POST);

?>

【问题讨论】:

  • 能否也发布您的 HTML 代码?
  • 请注意:unset return 后不会被执行,global 只能在函数内部使用。
  • HTML 太长,无法添加到帖子中。这是一个标准的 WordPress 页面。这是页面文本的内容:''
  • 你在哪里声明或设置你的登录变量?

标签: javascript php ajax mysqli


【解决方案1】:

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 的开头,以使您的意图更清晰(对您自己和可能正在查看您的代码的其他人来说:))

【讨论】:

  • 感谢您的全面回答。这已经让我连续两天发疯了。我需要它解释你的做法。
  • 很好的答案,虽然我个人会尽量避免整个全局变量混乱:-)
  • 没问题。祝你好运! jeroen 的建议非常正确:以后最好避免使用此类结构,以避开令人困惑的意大利面。 :)
【解决方案2】:

这有点混乱:您将异步和同步 javascript 混合在一起,您永远不知道自己处于什么状态以及处于什么状态。除此之外,您正在使用您重置和覆盖的全局 javascript 变量在您将它们用于异步请求时同步。

例如检查您的 firstCheck() 函数:这将重置您的 xmlhttp 变量(在另一个函数中...)并发出异步请求,但您已经在下一行检查异步请求的返回值当您检查 z 值时。该值(另一个全局变量......)只会在您的异步调用完成时设置,因此逻辑在那里没有位置。

您需要重新考虑您的架构,记住每次发出 ajax 请求时,结果都不会立即可用,会触发一个单独的事件 - readyState 更改 - 只有这样你才能做这些事情您想要处理从服务器返回的信息。

【讨论】:

  • 感谢您指出我没有看到的巨大缺陷。我是自学成才(很明显!),我真的需要一些外部视角。
猜你喜欢
  • 2015-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-21
  • 1970-01-01
相关资源
最近更新 更多