私は、Ajaxオブジェクトの構成をインターセプトする3つの異なる方法を試しました。
- 私の最初の試みはを使用しましたが
xhrFields
、これは1つのリスナーしか許可せず、ダウンロード(アップロードではなく)の進行状況にのみアタッチし、不要なコピーアンドペーストのように見えるものを必要とします。
- 2回目の試行で
progress
は、返されたpromiseに関数をアタッチしましたが、独自のハンドラーの配列を維持する必要がありました。XHRにアクセスする場所とjQuery XHRにアクセスする場所があるため、ハンドラーをアタッチするのに適したオブジェクトを見つけることができませんでしたが、遅延オブジェクト(その約束のみ)にはアクセスできませんでした。
- 3回目の試行では、ハンドラーをアタッチするためのXHRに直接アクセスできましたが、やはり多くのコピーアンドペーストコードが必要でした。
- 3回目の試行をまとめ、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 );