1

私はこれまでのところ運が悪かったので、phpスクリプトループのライブポーリングを実装しようとしています。これが私がこれまでに持っているものです:

フォーム送信時:

$.ajax({
data: $(this).serialize(),
success: showResponse,
url: 'process.php',
type: 'post'
});

function showResponse(){
$.ajax({
type: "GET",
url: "progress.php",
cache: false,
success: function(data) {
var response = $.parseJSON(data);
if (response.processing === true) {
console.log("Current Item: " + response.currentItem +
"Total Items: " + response.totalItems +
 "Percent Complete: " + response.percentComplete);
setTimeout(checkProgress, 1000);
});
}

process.phpスクリプトの場合:

session_start();
echo json_encode(array("processing" => true));
$totalItems = 10000000;
$_SESSION['totalItems'] = $totalItems;
$_SESSION['processing'] = true;
$_SESSION['error'] = false;
for ($i=0; $i <= $totalItems; $i++) {
$_SESSION['currentItem'] = $i;
$_SESSION['percentComplete'] = round(($i / $totalItems * 100));
}

進行中のphpスクリプト:

session_start();
echo json_encode(array(
"processing" => $_SESSION['processing'],
"error" => $_SESSION['error'],
"currentItem" => $_SESSION['currentItem'],
"totalItems" => $_SESSION['totalItems'],
"percentComplete" => $_SESSION['percentComplete']
)
);

ここでどこが間違っているのかわかりませんが、100%完了したらループするだけです。任意の提案をいただければ幸いです!

編集 私は上記をprocess.phpでapcを使用するように変更しました:

apc_store('totalItems', $totalItems);
apc_store('processing', true);
apc_store('error', false);
apc_store('currentItem', $i);
apc_store('percentComplete', round(($i / $totalItems * 100)));

そしてprogress.php内:

echo json_encode(array(
"processing" => apc_fetch('processing'),
"error" => apc_fetch('error'),
"currentItem" => apc_fetch('currentItem'),
"totalItems" => apc_fetch('totalItems'),
"percentComplete" => apc_fetch('percentComplete')
    )
);

それでも私が望んでいるように正しく機能しません、私は何か間違ったことをしていますか?スクリプトが完了するまではfalse値のみが表示され、セッションの使用が以前と同じように100%表示されます。何か案は?

4

1 に答える 1

5

セッション情報は排他的にのみ使用できるリソースであり、これを考慮していません。

具体的には、デフォルト設定でsession_startは、PHPはセッションデータを含むファイルの排他ロックを取得します。このファイルは、スクリプトが終了するかsession_write_close呼び出されるまでロック解除されません。

あなたの例でprocess.phpは、ロックを取得して動作を開始します。その間、(ロックのために)progress.phpしようとしますができません。進行状況情報の要求が満たされる前に、完了して終了する(したがってロックを解放する)のにsession_start()十分な時間が経過する必要があります。process.php

すぐに効果がある小さな変更は、ワーカーループ内session_write_closeから呼び出すことです。session_start

for ($i=0; $i <= $totalItems; $i++) {
    session_start();
    $_SESSION['currentItem'] = $i;
    $_SESSION['percentComplete'] = round(($i / $totalItems * 100));
    session_write_close();
}

これにより、2つのスクリプトが交互にセッションストレージファイルをロックできるようになるため、意図したとおりに機能していることがわかります。ただし、パフォーマンスは低下ます(これは、セッションストレージファイルを処理するための非常に失礼な方法です)。

現実の世界でこのようなことを行う必要がある場合は、セッションデータ以外の何かを利用して、PHPスクリプト間でこの情報交換を可能にする必要があります(たとえば、APCやmemcachedなどのメモリ内キャッシュ)。

于 2013-01-28T19:21:20.877 に答える