2011-02-23 49 views
3

我對jQuery實現它的AJAX方法很新鮮。jquery ajax調用不是異步的

我有一個簡單的設置,訪問兩個不同的頁面,一個需要10秒鐘完成(我有一個計時器設置)和一個檢查第一頁的狀態。

這兩個函數是progressCheck(),它每秒鐘以最新的狀態請求它的頁面,beginLogin()需要10秒鐘來加載。我在服務器上的用戶對象中設置了一個值,這兩個頁面都通過symfony 1.4訪問。

問題是,progressCheck()工作正常,直到我點擊beginLogin(),然後在beginLogin()完成之前沒有更改。我有兩個函數設置爲異步運行。我知道這一定是一件簡單的事情,但我無所適從。

我跑了Firebug的 - 淨運行此頁面時,其結果是: AJAX Net calls

了一批progressCheck()的等待期間爲10秒的電話叫,但淨說,他們在〜200毫秒跑沒有任何等待時間。

任何想法?下面

代碼:

<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 下面是返回數據爲兩頁的兩個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); 



} 
+3

檢查您在服務器端設置的共享用戶對象,它可能在beginLogin()訪問它時被鎖定,所以下一個對progresscheck()的請求正在等待在服務器端釋放該鎖。 – 2011-02-23 04:59:20

+0

是您在線託管的服務器端代碼嗎? – Anurag 2011-02-23 05:15:24

+0

@Furqan用戶對象只能被該特定用戶訪問,所以我設置了保存到數據庫的功能並在兩個瀏覽器中打開了相同的頁面。我點擊'beginLogin()'的瀏覽器掛了10秒,而正在運行'progressCheck()'的第二個瀏覽器在正確的時間更新了新值。 – Patrick 2011-02-23 05:54:46

回答

7

我發現了javascript調用掛起的原因。

爲防止race condition與用戶會話數據一起發生,PHP會鎖定數據直到出現兩種情況之一。

  1. 先前稱爲PHP腳本調用session_write_close()

  2. 先前調用的PHP腳本完成處理並隱式調用session_write_close()

繼到服務器的呼叫不調用session_start()應該讓真正的異步調用的邏輯,我創建了剛剛吐出了一個簡單的字符串虛擬PHP頁面,並呼籲該頁面每秒,而10第二個腳本跑了。它運行完美。

解決方案來自symfony論壇上的this discussion

+0

我面臨着同樣的問題,如何整合這個解決方案與codeingniter行動? – 2015-08-21 06:13:11

0

什麼像

我退學嘗試抓住並使您的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('<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; 
} 
+0

我把它插入到我的代碼中,它仍然掛起,直到10秒的腳本完成,然後我得到了所有progressCheck()那被稱爲在10秒 – Patrick 2011-02-25 01:13:33