Есть ли события обновления прогресса в jQuery ajax?
У меня есть давно запущенная задача, которая вызывается с помощью jquery ajax. Я использую плагин пользовательского блока, чтобы показать "загрузка". есть ли в любом случае, я могу отправлять сообщения о прогрессе обратно клиенту, чтобы показать прогресс и обновить его в сообщении плагина block ui.
Так что это покажет (как сервер выполняет свою работу) .,
"Загрузка первого источника..."
"Загрузка второго источника..."
"Загрузка третьего источника..."
"Анализ результатов..."
6 ответов
Из того, что я видел в случае загрузки материала - люди создают отдельный шлюз и запрашивают информацию о прогрессе, так как он доступен только на стороне сервера. Но я думаю, что это не самое лучшее в вашем случае.
Если вы хотите загружать данные с информацией о прогрессе или разрешать серверу получать информацию о прогрессе во время генерации вывода, тогда вам нужна потоковая передача http. Здесь красиво покрыто. По сути, это один http-запрос, на который сервер отвечает частями в течение минуты или около того (следовательно, отправляет данные, когда хочет), а затем открывается новое соединение.
Это было настоящим открытием для меня;)
[редактировать]
В настоящее время существует множество доступных более совершенных методов, и все они заключены в Socket.IO - веб-сокеты с отступлением от других методов, включая потоковую передачу по протоколу http.
Socket.IO - это модуль для nodeJS, но есть и другие похожие реализации. Я уже обменялся некоторыми пакетами с реализацией JAVA Socket.IO с https://github.com/Atmosphere/atmosphere
Один из способов - использовать HTTP-обработчики и AJAX с jQuery.
1. Инициируйте запрос на стороне сервера
$("#btnCreateInvoice").click(function() {
$.ajax({ type: "POST", url: "YourHttpHandler.ashx",
contentType: "text/html; charset=utf-8",
dataType: "html",
success: function(data) { start the block UI }
});
});
2. Опрос
Далее вам нужно опросить сервер с интервалом "t" и получить статус. Для этого нам нужно вызывать функцию с интервалом 't', которая инициировала бы вызов AJAX HTTP Handler для получения статуса.
$(function() {
setInterval(updateStatus, 't');
});
function updateStatus() {
$.ajax({ type: "POST", url: "GetStatusHandler.ashx",
contentType: "text/html; charset=utf-8",
dataType: "html",
success: function(data) { process 'data' here and update the block UI message box }
});
}
В вашем случае, GetStatusHandler.ashx может вернуть полный innerHtml для статуса. Например, при первом вызове он вернет "Загрузка первого источника...", а затем может вернуть:
Loding Первый источник...
Загрузка Второй источник...
и так далее.
Я хотел бы, чтобы каждый запрос AJAX возвращал ответ JSON, содержащий сообщение, данные и следующий URL-адрес для запроса: {message: "Loading second resource...", data: ..., next_url: "/next_part"}
Перед вашим первым AJAX-запросом установите для сообщения BlockUI значение "Загрузка...". Получив ответ, установите в сообщении BlockUI сообщение, полученное вами после вызова AJAX. Затем выполните следующий вызов AJAX со значением "next_url" и т. Д., Зацикливаясь до тех пор, пока вы не выполните все задачи.
Если вы загружаете один большой набор данных, но по частям, вы можете захотеть сделать что-то вроде шаблона проектирования с прогрессивной загрузкой, но также установить сообщение о ходе выполнения при получении каждого ответа.
Я только недавно узнал о проекте, который делает ajax "push". Вы можете проверить это:
Насколько я знаю, есть несколько других проектов, которые делают подобные вещи, это самый правильный способ: "отправлять сообщения о прогрессе обратно клиенту", когда другое решение требует запрос на опрос о прогрессе (все еще очень законный и хороший решение).
То, что вы пытаетесь сделать, это нечто похожее на комету. Традиционные ("некометные") веб-серверы не предназначены для такой модели транзакций и поэтому не являются желаемым решением.
Я предлагаю разбить обработку по одному клиентскому запросу на источник данных:
function loadData() {
// Each call passes callback(id) as a success handler
fireAsynchronousRequest("source1");
fireAsynchronousRequest("source2");
fireAsynchronousRequest("source3");
}
function callback(var source) {
if (source == "source1") {
updateStatus("Source 1 loaded");
}
else if (source == "source2") {
updateStatus("Source 2 loaded");
}
}
Это пример асинхронного решения. Вы можете реализовать обработку состояний в callback()
если вам нужно, чтобы это было синхронно.
Ну, у меня была похожая ситуация, и я решаю ее другим подходом. Это ОЧЕНЬ уродливое решение, я знаю это, поэтому, пожалуйста, не начинайте указывать, насколько это плохо, потому что я знаю это, но это было нормально для того, что мне нужно.
Я помещаю прогресс в файл на стороне сервера. Например, у меня есть файл process.php, который должен выполнить большую работу, и до его завершения требуется некоторое время, поэтому пользователь нервничает и закрывает браузер (не слишком хорошо). Таким образом, process.php сохраняет некоторые выходные данные в файл на сервере. На странице, которая называется process.php, у меня есть небольшой div, span или что-то еще, где я хочу отобразить прогресс, но я предлагаю div. Каждую X миллисекунду или секунду я загружаю другой сценарий с сервера в div, скажем, display_info.php. Теперь display_info.php читает файл, который был обработан process.php, а содержимое отображается в div.
Вы должны быть осторожны, чтобы выходные данные из process.php были уникальными для каждого случая, в противном случае вы запутаете вывод информации в браузерах.
Эмиль