ti-enxame.com

Obtendo atualizações de progresso (via AJAX) em uma ação do controlador sem bloquear

Eu tenho um controlador com uma ação que aceita solicitações pelo AJAX, faz alguma manipulação de dados e retorna alguns dados:

function publicDirectoryAjaxSearch(){
    // Check the form token
    JSession::checkToken('get') or die('Invalid Token');

    // Don't show PHP errors in raw output
    ini_set('display_errors', 'Off');

    // Sort out the session status
    $session = JFactory::getSession();
    $session->set('getOrganisationsStatus', 'Searching...');

    // Get orgs
    $response = $this->doPublicDirectorySearch();

    // Get the document object.
    $document = JFactory::getDocument();

    // Set the MIME type for JSON output.
    $document->setMimeEncoding('application/json');

    // Change the suggested filename.
    JResponse::setHeader('Content-Disposition','attachment;filename="result.json"');

    echo json_encode($response);
}

Esse método pode demorar um pouco, então estou usando JSession para armazenar uma variável de status getOrganisationStatus que pode ser verificada periodicamente via AJAX para ver até que ponto o $this->doPublicDirectorySearch() método ficou ...

function doPublicDirectorySearch(){
    ...
    while($running)
         $session->set('getOrganisationsStatus', 'Fetched '.$handled."/".$totalResults." results.");
    ...
}

No entanto, estou tendo alguns problemas. Se eu definir o manipulador de sessão de configuração global do Joomla como Banco de dados , a variável de sessão getOrganisationsStatus sempre parecerá 'atrasar' uma solicitação de dados para trás. Por exemplo (na preparação para este exemplo, limpei todas as sessões existentes):

  1. Faça uma solicitação de dados via AJAX para publicDirectoryAjaxSearch
  2. Defina um intervalo para obter a variável da sessão de status da solicitação sobre AJAX como publicDirectorySearchStatus
  3. Solicitação de dados ainda em execução. O valor da sessão é alterado conforme $this->doPublicDirectorySearch() funciona através dos dados
  4. Chamada de status feita de setInterval para publicDirectorySearchStatus. A variável de sessão retornada está vazia (esta etapa se repete no intervalo)
  5. publicDirectoryAjaxSearch solicitação de dados concluída. O método retorna o objeto JSON
  6. Chamada final de status feita sobre AJAX de setInterval para publicDirectorySearchStatus.) Os dados retornados (a variável de sessão) agora mostram o texto correto, conforme definido no método de solicitação de dados.

Se eu definir a configuração global do Joomla para usar Nenhuma como manipulador de sessões (ou seja, o PHP é um manipulador baseado em arquivos), o script será bloqueado (como - PHP bloqueia o arquivo da sessão quando um script o acessa, então a chamada AJAX para descobrir o status precisa esperar até que o método de atualização da variável da sessão termine - derrotando um pouco o ponto ).

Onde eu estou errando? Como posso..

  1. Faça uma ligação para obter dados (leva algum tempo)
  2. Faça uma chamada separada para obter uma variável de sessão que está sendo manipulada ao longo do tempo pela primeira chamada
2
codinghands

Todas as suas solicitações de página compartilham a mesma sessão do usuário. Portanto, se você chamar várias páginas, de forma assíncrona, na mesma sessão, poderá encontrar uma condição de corrida . http://en.wikipedia.org/wiki/Race_condition

Como PHP não é multithreading, não há mecanismos de bloqueio para evitar esses casos).

A melhor solução é evitar a condição: reorganize o loop principal e mova o controle para o lado do Ajax. Dessa maneira, o navegador chama uma inicialização , o loop interno (- === - =)) como quantas vezes for necessário e a finalização .

  • Você tem o controle para mostrar o status do progresso
  • Se você tiver milhares de itens para processar, poderá definir lotes discretos de itens para processar (em vez de um por um)
2
Anibal