Веб-серверы не могут передавать незапрошенные данные клиенту; они подчиняются циклу запрос-ответ. Альтернативой является использование очереди сообщений со значительным увеличением сложности.
Опрос от клиента не так уж и плох; веб-серверы отлично справляются со многими короткими запросами, и интервал опроса в 2-3 секунды должен быть достаточно быстрым.
Вот метод опроса, который мне нравится использовать. Он асинхронно ожидает ответа до возврата к опросу (требуется jQuery):
function poll(url, task, progressBar, resultsCallback,
timeoutMillis, pollIntervalMillis) {
$.ajax({
url: url,
type: 'GET',
dataType: 'json',
timeout: timeoutMillis,
data: 'action=poll&task='+task,
success: (function(response, status, xhr) {
if ('progress' in response) {
// update the UI with the progress
progressBar.setValue(response.progress);
}
if ('status' in response) {
if (response.status == 'pending') {
// task is not finished, continue polling
setTimeout((function() {
poll(url, task, progressBar, resultsCallback,
timeoutMillis, pollIntervalMillis);
}), pollIntervalMillis);
}
else {
// task completed
if (response.status == 'cancelled') {
progressBar.setColor('red');
progressBar.setText("Task '"+task+"' was cancelled");
}
else {
progressBar.setColor('green');
progressBar.setText("Task '"+task+"' complete");
}
// GET the results
$.ajax({
url: url,
type: 'GET',
timeout: timeoutMillis,
data: 'action=results&task='+task,
success: (function(response, status, xhr) {
resultsCallback(response, status, xhr);
}),
error: error
});
}
}
}),
error: error
});
function error(xhr, status, err) {
alert('Failure to communicate with server: ' + status + ', ' + err);
}
}
А ваш серверный код должен отвечать на опросы примерно так:
{"progress" : 42, "status" : "pending"}