深刻理解ajax系列第五篇——進度事件

前面的話

  通常地,使用readystatechange事件探測HTTP請求的完成。XHR2規範草案定義了進度事件Progress Events規範,XMLHttpRequest對象在請求的不一樣階段觸發不一樣類型的事件,因此它再也不須要檢査readyState屬性。這個草案定義了與客戶端服務器通訊有關的事件。這些事件最先其實只針對XHR操做,但目前也被其餘API(如File API)借鑑。本文將詳細介紹進度事件php

 

基礎

  有如下6個進度事件html

  loadstart:在接收到響應數據的第一個字節時觸發apache

  progress:在接收響應期間持續不斷地觸瀏覽器

  error:在請求發生錯誤時觸發服務器

  abort:在由於調用abort()方法而終止鏈接時觸發網絡

  load:在接收到完整的響應數據時觸發app

  loadend:在通訊完成或者觸發error、abort或load事件後觸發post

  timeout:超時發生時觸發spa

  [注意]IE9-瀏覽器不支持以上事件(IE9瀏覽器僅支持load事件)code

  每一個請求都從觸發loadstart事件開始,接下來,一般每隔50毫秒左右觸發一次progress事件,而後觸發load、error、abort或timeout事件中的一個,最後以觸發loadend事件結束

  對於任何具體請求,瀏覽器將只會觸發load、abort、timeout和error事件中的一個。XHR2規範草案指出一旦這些事件中的一個發生後,瀏覽器應該觸發loadend事件

 

load

  響應接收完畢後將觸發load事件,所以也就沒有必要去檢查readyState屬性了。但一個完成的請求不必定是成功的請求,例如,load事件的處理程序應該檢查XMLHttpRequest對象的status狀態碼來肯定收到的是「200 OK」而不是「404 Not Found」的HTTP響應

<button id="btn">獲取信息</button>
<div id="result"></div>
<script>
btn.onclick = function(){
    //建立xhr對象
    var xhr;
    if(window.XMLHttpRequest){
        xhr = new XMLHttpRequest();
    }else{
        xhr = new ActiveXObject('Microsoft.XMLHTTP');
    }
    //進度事件
    xhr.onload = function(){
        if(xhr.status == 200){
            result.innerHTML += xhr.responseText;
        }
    }
    //發送請求
    xhr.open('get','message.xml',true);
    xhr.send();
}
</script>        

progress

  progress事件會在瀏覽器接收新數據期間週期性地觸發。而onprogress事件處理程序會接收到一個event對象,其target屬性是XHR對象,但包含着三個額外的屬性:lengthComputable、loaded和total。其中,lengthComputable是一個表示進度信息是否可用的布爾值,loaded表示已經接收的字節數,total表示根據Content-Length響應頭部肯定的預期字節數。有了這些信息,就能夠爲用戶建立一個進度指示器了

<button id="btn">獲取信息</button>
<div id="result"></div>
<div id="music"></div>
<script>
btn.onclick = function(){
    //建立xhr對象
    var xhr;
    if(window.XMLHttpRequest){
        xhr = new XMLHttpRequest();
    }else{
        xhr = new ActiveXObject('Microsoft.XMLHTTP');
    }
    //進度事件
    xhr.onprogress = function(e){
        e = e || event;
        if (e.lengthComputable){
            result.innerHTML = "Received " + e.loaded + " of " + e.total + " bytes";
        }
    };
    xhr.onload = function(e){
        var data = xhr.response;
        e = e || event;
        if(xhr.status == 200){
            var audio = document.createElement('audio');
            audio.onload = function(){
                URL.revokeObjectURL(audio.src);
            }
            audio.src = URL.createObjectURL(data);
             console.log(audio);
            audio.setAttribute('controls','');
            if(!music.innerHTML){
                music.appendChild(audio);
            }
        }
    };
    //發送請求
    xhr.open('get','myocean.mp3',true);
    xhr.responseType = 'blob';
    xhr.send();
}
</script>    

上傳進度

  除了爲監控HTTP響應的加載定義的這些有用的事件外,XHR2也給出了用於監控HTTP請求上傳的事件。在實現這些特性的瀏覽器中,XMLHttpRequest對象將有upload屬性。upload屬性值是一個對象,它定義了addEventListener()方法和整個progress事件集合,好比onprogress和onload(但upload對象沒有定義onreadystatechange屬性,upload僅能觸發新的事件類型)

  能僅僅像使用常見的progress事件處理程序同樣使用upload事件處理程序。對於XMLHttpRequest對象,設置XHR.onprogress以監控響應的下載進度,而且設置XHR.upload.onprogress以監控請求的上傳進度

<input type="file" name="file1" id="file1" style="display:none">
<button id="btn">上傳文件</button>
<div id="pro"></div>
<div id="result"></div>
<script>
btn.onclick = function(){
    file1.click();
    pro.innerHTML = result.innerHTML = '';
}
file1.onchange = function(){
    //建立xhr對象
    var xhr;
    if(window.XMLHttpRequest){
        xhr = new XMLHttpRequest();
    }else{
        xhr = new ActiveXObject('Microsoft.XMLHTTP');
    }
    var data = file1.files[0];
    //上傳事件
    xhr.upload.onprogress = function(e){
        e = e || event;
        if (e.lengthComputable){
            pro.innerHTML = "上傳進度爲:" + e.loaded + " of " + e.total + " bytes" + ';百分比爲:' + e.loaded/e.total;
        }
    }
    xhr.onload = function(e){
        var data = xhr.responseText;
        e = e || event;
        if(xhr.status == 200){
            result.innerHTML =  data;
        }
    };
    //發送請求
    xhr.open('post','pp.php',true);
    xhr.setRequestHeader("content-type",data.type);
    xhr.send(data);
}
</script>      
<?php
error_reporting(E_ALL & ~E_NOTICE);
touch($file);
if(preg_match('/image/',apache_request_headers()['content-type'])){
    $file = 'photo/test.jpg'; 
    binary_to_file($file);
    echo '文件上傳成功!';
}else{
    echo '文件格式不正確,請選擇圖片文件';
}
function binary_to_file($file){
    $content = $GLOBALS['HTTP_RAW_POST_DATA'];  // 須要php.ini設置
    if(empty($content)){
        $content = file_get_contents('php://input'); //不須要php.ini設置,內存壓力小
    }
    $ret = file_put_contents($file, $content, true);
    return $ret;
};
?>

 

其餘事件

  HTTP請求沒法完成有3種狀況,對應3種事件。若是請求超時,會觸發timeout事件。若是請求停止,會觸發abort事件。最後,像太多重定向這樣的網絡錯誤會阻止請求完成,但這些狀況發生時會觸發error事件

  能夠經過調用XMLHttpRequest對象的abort()方法來取消正在進行的HTTP請求。調用abort()方法在這個對象上觸發abort事件

  調用abort()的主要緣由是完成取消或超時請求消耗的時間太長或當響應變得無關時。假如使用XMLHttpRequest爲文本輸入域請求自動完成推薦。若是用戶在服務器的建議達到以前輸入了新字符,這時等待請求再也不有用,應該停止

  XHR對象的timeout屬性等於一個整數,表示多少毫秒後,若是請求仍然沒有獲得結果,就會自動終止。該屬性默認等於0,表示沒有時間限制

  若是請求超時,將觸發ontimeout事件

var xhr = new XMLHttpRequest();
btn.onclick = function(){
    xhr.abort();
};
xhr.ontimeout = function(){
    console.log('The request timed out.');
}
xhr.timeout = 100;
xhr.onabort = function(){
    console.log("The transfer has been canceled by the user.");
}
xhr.onerror = function(){
    console.log("An error occurred while transferring the file.");    
}
xhr.onloadend = function(){
    console.log("請求結束");    
}
相關文章
相關標籤/搜索