JQuery AJAX вызов не асинхронный - PullRequest
3 голосов
/ 23 февраля 2011

Я новичок в реализации jQuery его методов AJAX.

У меня есть простая настройка, которая обращается к двум разным страницам, одна из которых занимает 10 секунд (у меня установлен таймер), а другая -проверяет состояние первой страницы.

Обе функции: progressCheck(), который каждую секунду запрашивает у своей страницы последний статус, и beginLogin(), загрузка которого занимает 10 секунд.Я установил значение в пользовательском объекте на сервере, к которому обе страницы получают доступ через symfony 1.4.

Проблема заключается в том, что progressCheck() работает правильно, пока я не нажму beginLogin(), тогда никакие изменения не будут внесены, пока не закончится beginLogin().У меня обе функции настроены на асинхронный запуск.Я знаю, что это должно быть что-то простое, чтобы понять, но я в растерянности.

Я запустил Firebug - Net во время работы этой страницы, и результат: AJAX Net calls

ЧислоprogressCheck() вызываются в течение периода ожидания для 10-секундного вызова, но Net говорит, что они работали в течение ~ 200 мс без какого-либо времени ожидания.

Есть идеи?

Код ниже:

<code><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+'
«);предупреждение ( "завершение");}});} catch (e) {alert ("Произошла ошибка при входе в систему:" + e);вернуть ложь;} вернуть истину;} 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 ("Произошла ошибка при проверке хода выполнения:" + e);вернуть ложь;} check_id = setTimeout ('progressCheck ()', 1000);вернуть истину;} // установить функцию проверки прогресса для вызова каждую секунду var check_id = setTimeout ('progressCheck ()', 1000);function clearCheck () {try {clearTimeout (check_id);} catch (e) {alert ("Произошла ошибка при очистке чека:" + e);вернуть ложь;} вернуть истину;}

ОБНОВЛЕНИЕ Вот две функции 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);



}

Ответы [ 2 ]

7 голосов
/ 25 февраля 2011

Я обнаружил причину зависания вызова javascript.

Чтобы предотвратить возникновение условия гонки с данными сеанса пользователя, PHP блокирует данные, пока не произойдет одно из двух условий.

  1. Ранее вызванный PHP-скрипт вызывает session_write_close().

  2. Ранее вызванный PHP-скрипт завершает обработку и неявно вызывает session_write_close().

Следуя логике, согласно которой вызов сервера, который не вызывает session_start(), должен разрешать истинные асинхронные вызовы, я создал фиктивную страницу PHP, которая просто выплевывает простую строку и вызываетэта страница каждую секунду, пока запускается 10-секундный скрипт.Он работал отлично.

Решение пришло из чтения этого обсуждения на форумах Symfony.

0 голосов
/ 24 февраля 2011

Как насчет

Я отбросил триггеры и сделал ваш setTimeout похожим на check_id = setTimeout(progressCheck, 1000);

<code>function beginLogin(){
    var login_url = "http://example.com/home/loginScript";
    return $.ajax({
        url: login_url,
        success: function(data){
            $("#result_div").append('<pre>' + data + '
<ч /> '); предупреждение ( "завершение"); }, ошибка: функция (a, b, c) { console.log (а) console.log (б) console.log (с) } }); } function progressCheck () { var check_url = "http://example.com/home/checkLoginProgress"; var ajax = $ .ajax ({ url: check_url, success: function (data) { . $ ( "# Progress_div") добавить ( '
' + data + '
<ч />'); }, ошибка: функция (a, b, c) { console.log (а) console.log (б) console.log (с) } }); check_id = setTimeout (progressCheck, 1000); вернуть ajax; } // установить функцию проверки прогресса для вызова каждую секунду var check_id = setTimeout (progressCheck, 1000); function clearCheck () { пытаться { clearTimeout (check_id); } catch (e) { alert («Произошла ошибка при очистке чека:« + e); вернуть ложь; } вернуть истину; }
...