Создайте простую таблицу, подобную этой:
CREATE TABLE progress_data (
statusId int(4) NOT NULL AUTO_INCREMENT,
progress float DEFAULT NULL COMMENT 'percentage',
PRIMARY KEY (id_progress_data)
);
Код JQuery:
//this uses Jquery Timers http://plugins.jquery.com/project/timers
$('#bUpdate').click(function() {
//first obtain a unique ID of this operation - this has to by synchronized
$.ajaxSetup({'async': false});
$.post('ajax.php', {'operation': 'beginOperation'}, function(data) {
statusId = parseInt(data.statusId);
});
//now run the long-running task with the operation ID and other params as necessary
$.ajaxSetup({'async': true});
$.post('ajax.php', {'operation': 'updateSite', 'statusId': statusId, 'param': paramValue}, function(data) {
$('#progress_bar').stopTime('statusLog'); //long operation is finished - stop the timer
if (data.result) {
//operation probably successful
} else {
//operation failed
}
});
//query for progress every 4s, 'statusLog' is just the name of the timer
$('#progress_bar').everyTime('4s', 'statusLog', function() {
var elm = $(this);
$.post('ajax.php', {'operation': 'showLog', 'statusId': statusId}, function(data) {
if (data) {
//set bar percentage
$('#progress').css('width', parseInt(data.progress) + '%');
}
});
});
return false;
}
Код бэкэнда (в PHP):
if (isset($_POST['operation'])) {
ini_set("display_errors", false);
session_write_close(); //otherwise requests would block each other
switch ($_POST['operation']) {
/**
* Initialize progress operation, acquire ID (statusId) of that operation and pass it back to
* JS frontend. The frontend then sends the statusId back to get current state of progress of
* a given operation.
*/
case 'beginOperation': {
$statusId = //insert into progress_data
echo json_encode(array('statusId' => $statusId));
break;
}
/**
* Return back current progress state.
*/
case 'showLog': {
$result->progress = (float) //SELECT progress FROM progress_data WHERE statusId = $_POST['statusId']
echo json_encode($result);
break;
}
case 'updateSite': {
//start long running operation, return whatever you want to, during the operation ocassionally do:
UPDATE progress_data SET progress=... WHERE statusId = $_POST['statusId']
}
}
}
/* Terminate script, since this 'view' has no template, there si nothing to display.
*/
exit;
Я использовалэтот подход уже используется в 3 приложениях, и я должен сказать, что он очень надежный и быстрый (операция showLog - это просто простая инструкция SELECT).Также можно использовать сессию для хранения прогресса, но это приносит много проблем, так как сессия должна быть закрыта на запись (если она хранится в файлах), в противном случае запросы showLog AJAX будут ждать завершения длинной операции.(и теряет смысл).