web-dev-qa-db-ja.com

ブロックせずにコントローラーアクションで(AJAX経由で)進行状況の更新を取得する

AJAX経由でリクエストを受け入れ、いくつかのデータ操作を行い、いくつかのデータを返すアクションを持つコントローラーがあります。

_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);
}
_

このメソッドには時間がかかる場合があるため、JSessionを使用してステータス変数getOrganisationStatusを保存しています。これは、AJAXを介して定期的に確認でき、$this->doPublicDirectorySearch()メソッドが取得されました...

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

ただし、いくつか問題があります。 Joomlaグローバル構成セッションハンドラーをDatabaseに設定した場合、getOrganisationsStatusセッション変数は常に1つのデータ要求を「遅れ」ているように見えます。たとえば(この例の準備では、既存のすべてのセッションをクリアしました):

  1. AJAX to publicDirectoryAjaxSearch
  2. AJAX to publicDirectorySearchStatus
  3. データ要求はまだ実行中です。 $this->doPublicDirectorySearch()がデータを処理するときにセッション値が変化する
  4. SetIntervalからpublicDirectorySearchStatusへのステータス呼び出し。返されたセッション変数は空です(このステップはこの間隔で繰り返されます)
  5. publicDirectoryAjaxSearchデータリクエストが完了しました。メソッドがJSONオブジェクトを返す
  6. AJAX from setInterval to publicDirectorySearchStatus。に対して行われた最終ステータスコール。返されたデータ(セッション変数)は、データリクエストメソッドで設定された正しいテキストを表示するようになりました。

Joomlaグローバル設定をNoneをセッションハンドラー(つまり、PHPの組み込みファイルベースハンドラー)として使用するように設定すると、スクリプトは(- PHPはセッションファイルをロックします スクリプトがアクセスすると、AJAX呼び出しは、セッション変数を更新するメソッドが終了するまで待機する必要があります。 )。

どこがいけないの?どうやって..

  1. データを取得するために電話をかける(時間がかかる)
  2. 個別の呼び出しを行って、最初の呼び出しによって時間とともに操作されているセッション変数を取得する
2
codinghands

すべてのページリクエストが同じユーザーセッションを共有します。したがって、同じセッションで非同期に複数のページを呼び出すと、競合状態を見つけることができます。 http://en.wikipedia.org/wiki/Race_condition

PHPはマルチスレッドではないため、これらのケースを回避するためのロックメカニズムはありません。

最良の解決策は、この状態を回避することです。メインループを再編成し、コントロールをAjax側に移動します。このようにして、ブラウザは初期化内部ループを次のように呼び出します必要に応じて何度も、そしてファイナライズ

  • あなたはコントロールを持っているので、進行状況を表示できます
  • 処理するアイテムが何千もある場合、処理するアイテムの個別のバッチを(1つずつではなく)定義できます。
2
Anibal