我对jQuery实现它的AJAX方法很新鲜.
我有一个简单的设置,访问两个不同的页面,一个需要10秒钟完成(我有一个计时器设置)和一个检查第一页的状态.
这两个函数是progressCheck(),它每秒以最新状态请求其页面,而beginLogin()需要10秒才能加载.我在服务器上的用户对象中设置了一个值,两个页面都通过symfony 1.4访问.
问题是progressCheck()正常工作,直到我单击beginLogin(),然后在beginLogin()完成之前不会进行任何更改.我有两个函数设置为异步运行.我知道这一定很简单,但是我很茫然.
我在运行此页面时运行了Firebug-Net,结果是:
在10秒呼叫的等待期间调用了许多progressCheck(),但Net表示它们在没有任何等待时间的情况下运行了大约200毫秒.
有任何想法吗?
代码如下:
Begin Login
Check Progress
Clear Check
#progress_div
{
width: 800px;
height: 200px;
border: 1px solid #CCCCCC;
overflow: scroll;
background-color: #AAEEFF;
}
#result_div
{
width: 800px;
height: 300px;
border: 1px solid #CCCCCC;
overflow: scroll;
background-color: #FFEEAA;
}
function beginLogin()
{
try
{
var login_url = "http://example.com/home/loginScript";
$.ajax({
url: login_url,
success: function(data){
$("#result_div").append('
'+data+'
');
alert("finished");
}
});
}
catch(e)
{
alert("There was an error beginning the login: " + e);
return false;
}
return true;
}
function progressCheck()
{
try
{
var check_url = "http://example.com/home/checkLoginProgress";
$.ajax({
url: check_url,
success: function(data){
$("#progress_div").append('
'+data+'
');
}
});
}
catch(e)
{
alert("There was an error checking the progress: " + e);
return false;
}
check_id = setTimeout('progressCheck()', 1000);
return true;
}
// set progress checking function to call every second
var check_id = setTimeout('progressCheck()', 1000);
function clearCheck()
{
try
{
clearTimeout(check_id);
}
catch(e)
{
alert("There was an error clearing the check: " + e);
return false;
}
return true;
}
UPDATE
以下是两个PHP函数,它们返回两个页面调用的数据
define('DEBUG', true);
public function executeCheckLoginProgress(sfWebRequest $request)
{
if($this->getUser()->hasAttribute('login_script', 'sfGuardSecurityUser'))
$this->login_progress = $this->getUser()->getAttribute('login_script', -1, 'sfGuardSecurityUser');
else
$this->login_progress = '[undefined]';
$conn = $this->connectTestDb();
$query = sprintf("SELECT * FROM company_type WHERE id = 1;");
$result = mysql_query($query, $conn);
$this->login_progress = mysql_result($result, 0, 'name');
if($request->isXmlHttpRequest())
{ // this is an ajax all, only return value
$this->getResponse()->setHttpHeader("Content-type", "text/plain");
$this->getResponse()->setContent($this->login_progress);
return sfView::NONE;
}
}
public function executeLoginScript(sfWebRequest $request)
{
$user = $this->getUser();
if(!$user->hasAttribute('login_script', 'sfGuardSecurityUser'))
$user->setAttribute('login_script', 0, 'sfGuardSecurityUser');
$this->login_value = $user->getAttribute('login_script', 0, 'sfGuardSecurityUser');
$conn = $this->connectTestDb();
$query = sprintf("SELECT * FROM company_type WHERE id = 1;");
$result = mysql_query($query, $conn);
$this->login_value = mysql_result($result, 0, 'name');
$result = $user->assignAccessLevelIds();
if($result === true)
{
$this->login_value += 5;
$user->setAttribute('login_script', $this->login_value, 'sfGuardSecurityUser');
$query = sprintf("UPDATE company_type SET `name` = '%s' WHERE id = 1;", mysql_real_escape_string($this->login_value));
$result = mysql_query($query, $conn);
$this->login_progress = mysql_result($result, 0, 'name');
}
else
{
DataMan::logRawMessage('Unable to set access level user ['.$user->getAttribute('user_id', null, 'sfGuardSecurityUser'), sfLogger::WARNING);
}
// just for testing sleep!
if(DEBUG === true)
sleep(5);
$result = $user->assignCompanyIds();
if($result === true)
{
$this->login_value += 5;
$user->setAttribute('login_script', $this->login_value, 'sfGuardSecurityUser');
$query = sprintf("UPDATE company_type SET `name` = '%s' WHERE id = 1;", mysql_real_escape_string($this->login_value));
$result = mysql_query($query, $conn);
$this->login_progress = mysql_result($result, 0, 'name');
}
else
{
DataMan::logRawMessage('Unable to set company ids user ['.$user->getAttribute('user_id', null, 'sfGuardSecurityUser').'] '.__LINE__, sfLogger::WARNING);
}
// just for testing sleep!
if(DEBUG === true)
sleep(5);
}
解决方法:
我发现了javascript调用挂起的原因.
为了防止用户会话数据发生race condition,PHP会锁定数据,直到出现两种情况之一.
>之前调用的PHP脚本调用session_write_close().
>先前调用的PHP脚本完成处理并隐式调用session_write_close().
遵循不调用session_start()的服务器调用应允许真正的异步调用的逻辑,我创建了一个虚拟PHP页面,它只是吐出一个简单的字符串,并在10秒脚本运行时每隔一秒调用该页面.它跑得很好.
解决方案来自阅读symfony论坛上的this discussion.
标签:php,jquery,asynchronous,race-condition
来源: https://codeday.me/bug/20190730/1579613.html