jquery ajax调用不是异步的
我对jQuery实现它的AJAX方法很新鲜。
我有一个简单的设置,访问两个不同的页面,一个需要10秒钟才能完成(我有一个计时器设置)和一个检查第一页的状态。
这两个函数是progressCheck()
,它每秒以最新状态请求其页面,而beginLogin()
需要10秒才能加载。 我在服务器上的用户对象中设置了一个值,这两个页面都通过symfony 1.4访问。
问题是progressCheck()
正常工作,直到我单击beginLogin()
,然后在beginLogin()
完成之前不会进行任何更改。 我有两个函数设置为异步运行。 我知道这一定很简单,但我很茫然。
我在运行此页面时运行了Firebug – Net,结果是:
在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会锁定数据,直到出现两种情况之一。
以前调用的PHP脚本调用
session_write_close()
。之前调用的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; }