jquery ajax调用不是异步的

我对jQuery实现它的AJAX方法很新鲜。

我有一个简单的设置,访问两个不同的页面,一个需要10秒钟才能完成(我有一个计时器设置)和一个检查第一页的状态。

这两个函数是progressCheck() ,它每秒以最新状态请求其页面,而beginLogin()需要10秒才能加载。 我在服务器上的用户对象中设置了一个值,这两个页面都通过symfony 1.4访问。

问题是progressCheck()正常工作,直到我单击beginLogin() ,然后在beginLogin()完成之前不会进行任何更改。 我有两个函数设置为异步运行。 我知道这一定很简单,但我很茫然。

我在运行此页面时运行了Firebug – Net,结果是: AJAX网络电话

在10秒呼叫的等待期间调用了许多progressCheck() ,但Net表示它们在没有任何等待时间的情况下运行了大约200毫秒。

有任何想法吗?

代码如下:

    
#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; }

更新以下是两个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调用挂起的原因。

为了防止用户会话数据发生竞争条件 ,PHP会锁定数据,直到出现两种情况之一。

  1. 以前调用的PHP脚本调用session_write_close()

  2. 之前调用的PHP脚本完成处理并隐式调用session_write_close()

遵循不调用session_start()的服务器调用应该允许真正的异步调用的逻辑,我创建了一个虚拟PHP页面,它只是吐出一个简单的字符串,并在运行10秒脚本时每秒调用该页面。 它跑得很好。

解决方案来自阅读symfony论坛上的讨论。

怎么样的

我删除了try catch,并使你的setTimeout看起来像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('
' + data + '

'); 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('

' + data + '

'); }, 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; }