2011-08-01 1 views
12

내 페이지에 긴 폴링 요청이 있습니다. 서버 측의 스크립트는 20 초 후에 시간 초과로 설정됩니다.여러 AJAX 요청이 서로 지연됩니다.

따라서 긴 폴링이 "유휴 상태"이고 사용자가 다른 버튼을 누르면 이전 요청 스크립트가 시간 초과 될 때까지 새로운 요청 전송이 지연됩니다.

jQuery 측의 코드에는 아무런 문제가 없습니다. onclick-event가 지연되는 이유는 무엇입니까?

function poll() 
{ 
$.ajax({ 
    url: "/xhr/poll/1", 
    data: { 
     user_id: app.user.id 
    }, 
    type: "POST", 
    dataType: "JSON", 
    success: pollComplete, 
    error: function(response) { 
     console.log(response); 
    } 
}); 
} 

function pollComplete() 
{ 
    poll(); 
} 

function joinRoom(user_id) 
{ 
$.ajax({ 
    url: "/xhr/room/join", 
    dataType: "JSON", 
    type: "POST", 
    data: { 
     user_id: app.user.id, 
     room_id: room.id 
    } 
}); 
} 

<button id="join" onclick="javascript:joinRoom(2);">Join</button> 

############ PHP Controller on /xhr/poll 

$time = time(); 
while ((time() - $time) < 20) 
{ 
    $updates = $db->getNewStuff(); 

    foreach ($updates->getResult() as $update) 
     $response[] = $update->getResponse(); 

    if (!empty($response)) 
     return $response; 
    else 
     usleep(1 * 1000000); 

    return 'no-updates'; 
} 

"usleep"이 문제가 될 수 있습니까?

XHR Screenshot

+0

로컬 호스트에 문제가 있습니까 ?? –

+1

AJAX 호출을위한 PHP 코드는 세션을 활용합니까? –

답변

23

당신이 AJAX 처리 함수에서 세션을 사용하는 경우이 문제가 디스크에 실행됩니다 세션 데이터가 첫 번째 요청에 의해 잠겨 있기 때문에 각 후속 요청은 세션 데이터가 진행되기 전에 사용 가능한 상태가되기를 기다리고 끝납니다. 사실 비동기 호출이 서로를 차단하고 요청에 대한 선형 응답이 시간순으로 끝납니다 - 동기. (here's a reference article)

해결 방법은 더 이상 필요하지 않으면 세션을 닫는 즉시 session_write_close (docs)을 사용하는 것입니다. 이렇게하면 세션 데이터가 "잠금 해제"되므로 다른 후속 요청을 진행할 수 있습니다.

그러나이 또한 혼란 스러울 수 있습니다. 응답을 보내기 전에 바로 session_write_close으로 전화를 걸면 응답을 보내 자마자 세션 잠금이 풀려 있기 때문에 어떤 호의도 가지지 않습니다. 따라서 가능한 한 빨리 호출해야합니다. AJAX 요청에 대해 포스트 백 스타일 아키텍처를 사용하는 경우 이는 그리 나쁘지 않지만 큰 프레임 워크가 있고 요청 처리기가 일부일 뿐인 경우 더 많은 최상위 솔루션을 탐색해야합니다 비 블로킹 세션 사용으로 인해 하위 구성 요소가 프레임 워크가 기대하는 세션을 닫지 않도록합니다.

하나의 경로는 데이터베이스 세션과 함께 진행됩니다. 이 해결책의 장단점은이 답변의 범위를 벗어납니다. Google에서 철저한 토론을 확인하십시오. 또 다른 방법은 세션을 열고 변수를 추가 한 다음 닫는 함수를 사용하는 것입니다. 이 솔루션으로 경쟁 조건에 위험을 초래할 수 있지만 대략적인 개요는 다음과 같습니다.

function get_session_var($key, $default=null) { 
    if (strlen($key) < 1) 
     return null; 
    if (!isset($_SESSION) || !is_array($_SESSION)) { 
     session_start(); 
     session_write_close(); 
    } 
    if (array_key_exists($key, $_SESSION)) 
     return $_SESSION[$key]; 
    return $default; 
} 
function set_session_var($key, $value=null) { 
    if (strlen($key) < 1) 
     return false; 
    if ($value === null && array_key_exists($key, $_SESSION)) { 
     session_start(); 
     unset($_SESSION[$key]); 
    } elseif ($value != null) { 
     session_start(); 
     $_SESSION[$key] = $value; 
    } else { 
     return false; 
    } 
    session_write_close(); 
    return true; 
} 
+1

제안 된 솔루션을 정확히 사용하지 않았지만'session_write_close() '와 관련된 힌트가 완전한! 내 요청은 세션을 사용하고 있었고 사용 중지는 완벽하게 작동했습니다. –

+1

'session_write_close()'가 내 문제를 해결했습니다. 감사합니다! –

1

이 2 요청 규칙과 일치 소리 - 브라우저는 시간이 주어진 하나의 동일한 호스트에 두 개의 동시 연결을 할 수 있습니다. 그렇게 말하면서, 당신은 긴 투표 (수신)와 채널을 보내는 것이 좋을 것입니다. $ (function() {...?)을 사용하여 페이지로드 후 긴 폴링을 시작 하시겠습니까? 브라우저가 아닌 클라이언트에서 요청이 지연되고 있습니까? 방화벽에서 무엇을 보시겠습니까?

+0

예, 요청이 몇 초 동안 불그스레 할 정도로 보이지 않기 때문에 확실합니다. 그러나 폴링이 끝나고 처음부터 시작되면 위 스크린 샷과 마찬가지로 요청이 표시됩니다. –

+0

폴링없이 AJAX 만 테스트했고 완료하려면 약 800ms가 걸렸습니다. 폴링이 실행 중일 때는 항상 2 초 이상 걸립니다. –

+0

여기에 동의합니다. 새로운 브라우저는 더 많은 것을 허용하지만 (FF는 6을 허용하고 IE 8은 8을 허용합니다). – Mrchief

1

하나 당신이 할 수있는 것은, 당신이 실행 설문 조사를 중단하고 먼저 요청을 실행 한 다음 다시 설문 조사를 시작할 수 있습니다.

//make sure pollJqXhr.abort is not undefined 
var pollJqXhr={abort:$.noop}; 

function poll() 
{ 
    //assign actual jqXhr object 
    pollJqXhr=jQuery.ajax({youroptions}); 
} 

function pollComplete() 
{ 
    poll(); 
} 


function joinRoom(user_id) 
{ 
    //pause polling 
    pollJqXhr.abort(); 

    jquery.ajax({ 
      /*options here*/ 
      success:function() 
      { 
       /*Your codes*/ 

       //restart poll 
       poll() 
      } 
    }); 
} 
+1

원인이 아닌 증상을 치료하는 것 같습니다. –