问题
I am fresh to jQuery's implementation of it's AJAX methods.
I have a simple setup that accesses two different pages, one which takes 10 seconds to complete (I have a timer set on it) and one which checks on the status of the first page.
The two functions are progressCheck()
which requests its page every second with the latest status and beginLogin()
which takes 10 seconds to load. I set a value in the user object on the server that both pages access through symfony 1.4.
The issue is that the progressCheck()
works correctly until I click beginLogin()
, then no changes are made until beginLogin()
finishes. I have both functions setup to run asynchronously. I know it must be something simple to figure out, but I am at a loss.
I ran Firebug - Net while running this page and the result is:
A number of the progressCheck()
are called during the wait period for the 10 second call, but Net says they ran in ~200 ms without any wait time.
Any ideas?
Code below:
<button onclick="beginLogin();">Begin Login</button>
<button onclick="progressCheck();">Check Progress</button>
<button onclick="clearCheck();">Clear Check</button>
<br/>
<div id="result_div">
</div>
<div id="progress_div">
</div>
<style type="text/css">
#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;
}
</style>
<script type="text/javascript">
function beginLogin()
{
try
{
var login_url = "http://example.com/home/loginScript";
$.ajax({
url: login_url,
success: function(data){
$("#result_div").append('<pre>'+data+'</pre><hr/>');
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('<pre>'+data+'</pre><hr/>');
}
});
}
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;
}
</script>
UPDATE Here are the two PHP functions that returns the data for the two page calls
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);
}
回答1:
I have discovered the cause of the javascript call hanging.
To prevent a race condition from occurring with user session data, PHP locks the data until one of two conditions occur.
The previously called PHP script calls
session_write_close()
.The previously called PHP script completes processing and implicitly calls
session_write_close()
.
Following the logic that a call to the server that does not call session_start()
should allow true asynchronous calls, I created a dummy PHP page that just spits out a simple string and called to that page every second while the 10 second script ran. It ran perfectly.
The solution came from reading this discussion on the symfony forums.
回答2:
What about something like
I dropped the try catch's and made your setTimeout's to look like check_id = setTimeout(progressCheck, 1000);
function beginLogin(){
var login_url = "http://example.com/home/loginScript";
return $.ajax({
url: login_url,
success: function(data){
$("#result_div").append('<pre>' + data + '</pre><hr/>');
alert("finished");
},
error: function(a, b, c){
console.log(a)
console.log(b)
console.log(c)
}
});
}
function progressCheck(){
var check_url = "http://example.com/home/checkLoginProgress";
var ajax = $.ajax({
url: check_url,
success: function(data){
$("#progress_div").append('<pre>' + data + '</pre><hr/>');
},
error: function(a, b, c){
console.log(a)
console.log(b)
console.log(c)
}
});
check_id = setTimeout(progressCheck, 1000);
return ajax;
}
// 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;
}
来源:https://stackoverflow.com/questions/5087097/jquery-ajax-call-not-asynchronous