Каков самый чистый способ получить ход запроса JQuery ajax?
В простом javascript очень просто: нужно просто прикрепить обратный вызов к {XMLHTTPRequest}.onprogress
var xhr = new XMLHttpRequest();
xhr.onprogress = function(e){
if (e.lengthComputable)
var percent = (e.loaded / e.total) * 100;
};
xhr.open('GET', 'http://www...', true);
xhr.onreadystatechange = function() {
...
};
xhr.send(null);
но я делаю сайт ajax, который загружает html-данные с помощью JQuery ($.get()
или $.ajax()
), и мне было интересно, какой из них - лучший способ получить ход запроса, чтобы отобразить его с небольшим но любопытно, я не нахожу ничего полезного в документации JQuery...
Ответы
Ответ 1
Что-то вроде этого для $.ajax
(только HTML5):
$.ajax({
xhr: function() {
var xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener("progress", function(evt) {
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
//Do something with upload progress here
}
}, false);
xhr.addEventListener("progress", function(evt) {
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
//Do something with download progress
}
}, false);
return xhr;
},
type: 'POST',
url: "/",
data: {},
success: function(data){
//Do something on success
}
});
Ответ 2
jQuery уже реализовал promises, поэтому лучше использовать эту технологию и не переводить логику событий в options
. Я создал плагин jQuery, который добавляет перспективы прогресса, и теперь он прост в использовании, как и другие promises:
$.ajax(url)
.progress(function(){
/* do some actions */
})
.progressUpload(function(){
/* do something on uploading */
});
Проверьте это на github
Ответ 3
jQuery имеет функцию AjaxSetup()
, которая позволяет вам регистрировать глобальные обработчики ajax, такие как beforeSend
и complete
для всех вызовов ajax а также разрешить доступ к объекту xhr
для достижения прогресса, который вы ищете
Ответ 4
Я попробовал три разных способа перехвата конструирования объекта Ajax:
- Моя первая попытка использовала
xhrFields
, но она учитывает только одного слушателя, только присоединяет к прогрессу загрузки (но не выгрузки) и требует того, что кажется ненужным копированием и вставкой.
- Моя вторая попытка прикрепила функцию
progress
к возвращенному обещанию, но мне пришлось поддерживать собственный массив обработчиков. Я не смог найти хороший объект для присоединения обработчиков, потому что в одном месте у меня был бы доступ к XHR, а в другом - к jQuery XHR, но у меня никогда не было доступа к отложенному объекту (только его обещание).
- Моя третья попытка дала мне прямой доступ к XHR для присоединения обработчиков, но снова потребовалось много кода для копирования и вставки.
- Я завершил свою третью попытку и заменил jQuery
ajax
своей собственной. Единственный потенциальный недостаток - вы больше не можете использовать собственную настройку xhr()
. Вы можете сделать это, проверив, является ли функция options.xhr
.
Я на самом деле называю свою функцию promise.progress
xhrProgress
, чтобы потом легко найти ее. Возможно, вы захотите назвать это как-то еще, чтобы отделить слушателей для загрузки и выгрузки. Я надеюсь, что это поможет кому-то, даже если оригинальный плакат уже получил то, что ему нужно.
(function extend_jQuery_ajax_with_progress( window, jQuery, undefined )
{
var $originalAjax = jQuery.ajax;
jQuery.ajax = function( url, options )
{
if( typeof( url ) === 'object' )
{options = url;url = undefined;}
options = options || {};
// Instantiate our own.
var xmlHttpReq = $.ajaxSettings.xhr();
// Make it use our own.
options.xhr = function()
{return( xmlHttpReq );};
var $newDeferred = $.Deferred();
var $oldPromise = $originalAjax( url, options )
.done( function done_wrapper( response, text_status, jqXHR )
{return( $newDeferred.resolveWith( this, arguments ));})
.fail( function fail_wrapper( jqXHR, text_status, error )
{return( $newDeferred.rejectWith( this, arguments ));})
.progress( function progress_wrapper()
{
window.console.warn( "Whoa, jQuery started actually using deferred progress to report Ajax progress!" );
return( $newDeferred.notifyWith( this, arguments ));
});
var $newPromise = $newDeferred.promise();
// Extend our own.
$newPromise.progress = function( handler )
{
xmlHttpReq.addEventListener( 'progress', function download_progress( evt )
{
//window.console.debug( "download_progress", evt );
handler.apply( this, [evt]);
}, false );
xmlHttpReq.upload.addEventListener( 'progress', function upload_progress( evt )
{
//window.console.debug( "upload_progress", evt );
handler.apply( this, [evt]);
}, false );
return( this );
};
return( $newPromise );
};
})( window, jQuery );
Ответ 5
Выполните шаги, чтобы отобразить ход выполнения запроса Ajax:
- Создайте Spinner, используя Html & CSS или используйте Bootstrap Spinner.
- Отобразите счетчик, когда конечный пользователь запрашивает данные AJAX для бесконечного цикла или для порогового предельного времени.
- Итак, после результата УСПЕХА/ОШИБКИ AJAX-запроса удалите Spinner, который отображается в данный момент, и покажите свои результаты.
Чтобы упростить процесс, я рекомендую использовать классы JS для динамического отображения & Для этого прячем вертушку.
Надеюсь, это поможет!
Ответ 6
http://www.htmlgoodies.com/beyond/php/show-progress-report-for-long-running-php-scripts.html
Я искал аналогичное решение и нашел, что он используется полностью.
var es;
function startTask() {
es = new EventSource('yourphpfile.php');
//a message is received
es.addEventListener('message', function(e) {
var result = JSON.parse( e.data );
console.log(result.message);
if(e.lastEventId == 'CLOSE') {
console.log('closed');
es.close();
var pBar = document.getElementById('progressor');
pBar.value = pBar.max; //max out the progress bar
}
else {
console.log(response); //your progress bar action
}
});
es.addEventListener('error', function(e) {
console.log('error');
es.close();
});
}
и выходы сервера
header('Content-Type: text/event-stream');
// recommended to prevent caching of event data.
header('Cache-Control: no-cache');
function send_message($id, $message, $progress) {
$d = array('message' => $message , 'progress' => $progress); //prepare json
echo "id: $id" . PHP_EOL;
echo "data: " . json_encode($d) . PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
}
//LONG RUNNING TASK
for($i = 1; $i <= 10; $i++) {
send_message($i, 'on iteration ' . $i . ' of 10' , $i*10);
sleep(1);
}
send_message('CLOSE', 'Process complete');