Javascript 获取jQueryAjax请求进度的最干净的方法是什么?

Javascript 获取jQueryAjax请求进度的最干净的方法是什么?,javascript,ajax,jquery,xmlhttprequest,Javascript,Ajax,Jquery,Xmlhttprequest,在普通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.onread

在普通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站点,它使用JQuery下载html数据(
$.get()
$.ajax()
),我想知道哪种方法是获取请求进度的最佳方法,以便用一个小进度条显示请求,但奇怪的是,我在JQuery文档中找不到任何有用的东西…

JQuery有一个函数,它允许您为所有ajax调用注册全局ajax处理程序,例如在发送之前注册
完成
,并允许您访问
xhr
对象来完成您正在寻找的进程
$.ajax
(仅限HTML5):


我尝试了三种截取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 );
    

    我正在寻找一个类似的解决方案,并发现这一个使用充分

    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');
    
    标题(“内容类型:文本/事件流”);
    //建议防止缓存事件数据。
    标头(“缓存控制:无缓存”);
    函数send_message($id,$message,$progress){
    $d=array('message'=>$message,'progress'=>$progress);//准备json
    echo“id:$id”;
    echo“data:”.json_encode($d).PHP_EOL;
    echo PHP_EOL;
    ob_flush();
    冲洗();
    }
    //长时间运行任务
    
    对于($i=1;$ijQuery已经实现了承诺,因此最好使用此技术,不要将事件逻辑移动到
    options
    参数。我制作了一个jQuery插件,添加了进度承诺,现在它与其他承诺一样易于使用:


    上查看,按照以下步骤显示Ajax请求的进度:

  • 使用Html和CSS创建微调器或使用引导微调器
  • 当最终用户请求无限循环或阈值限制时间的AJAX数据时,显示微调器
  • 因此,在AJAX请求的成功/错误结果之后,移除当前显示的微调器并显示结果
  • 为了方便起见,我建议您使用JS类动态显示和隐藏微调器


    我希望这会有帮助!

    这一个看起来很有希望用于html5Ooh谢谢大家!所以需要重写xhr。.奇怪的是,我用Chrome开发工具检查了所谓的
    jqXHR
    对象(由
    $.ajax()
    返回的xhr对象的包装器),并在其中找到了
    progress
    属性(还有
    中止
    完成
    成功
    ,等等),但在JQuery文档中,这一点是缺失的:我使用这个,它与其他答案完全相同,但我更喜欢更通用的东西。谢谢链接。你能在回答中包括一个例子吗?$.ajaxSetup({xhr:function(){console.log('setup xhr…);});还有一个例子可以回答这个问题吗?恐怕我无法给出一个让我做了大量的修改和阅读的答案,特别是当链接页面上没有任何关于进度的内容时。老实说,我对此表示怀疑,特别是考虑到该页面上的警告,即“注意:全局回调函数应该设置为各自的全局Ajax事件处理程序方法-
    .ajaxStart()
    .ajaxStop()
    .ajaxComplete()
    .ajaxError()
    .ajaxSuccess()
    .ajaxSend()
    ,而不是在
    $.ajaxSetup()的选项对象中
    :为将来的Ajax请求设置默认值。不建议使用它。所以我只是尝试实现您的解决方案,但这段代码有点过于专业,我无法理解-如何使用它?我在我的文档之前复制粘贴了您的整段代码。准备并尝试执行
    $.Ajax({…})。进度(函数(evl){console.log(evl);});
    但是什么也没发生。你能帮我吗?:)您使用的是哪个版本的jQuery?@FloSchild,请不要仅仅为了您自己的格式设置而编辑我的代码。我喜欢您使用IFI工厂的方式。我不知道这种技术!这是目前这里建议的最佳解决方案。这是一种可行且优雅的解决方案,但您可能知道它可能会破坏您现有的代码,因为它中断对已弃用的.success和.error的所有调用。它还会剥离您在jqXHR对象上设置的所有非标准属性。它不会为uploadProgress回调提供“this”上下文(可能与progress相同,但未测试)正如jqXHR的所有标准承诺一样。因此,您需要在闭包中传递上下文。我得到错误:
    TypeError:$.ajax(…).progress(…)。progressUpload不是一个函数
    。。。。
    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');
    
    $.ajax(url)
      .progress(function(){
        /* do some actions */
      })
      .progressUpload(function(){
        /* do something on uploading */
      });