我尝试了三种不同的方式来拦截 Ajax 对象的构造:
- 我的第一次尝试使用
xhrFields
了,但这只允许一个听众,只附加下载(而不是上传)进度,并且需要看似不必要的复制和粘贴。
- 我的第二次尝试将一个函数附加
progress
到返回的 Promise 上,但我必须维护自己的处理程序数组。我找不到一个好的对象来附加处理程序,因为一个地方我可以访问 XHR,另一个地方我可以访问 jQuery XHR,但我从来没有访问过延迟对象(只有它的承诺)。
- 我的第三次尝试让我可以直接访问 XHR 以附加处理程序,但再次需要大量复制和粘贴代码。
- 我结束了我的第三次尝试并
ajax
用我自己的替换了 jQuery。唯一的潜在缺点是您不能再使用自己的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 );