前沿:對於此篇隨筆,完是簡要寫了幾個重要的地方,具體實現細節完在提供的源碼作了筆記ajax
<一>ajax基本要點介紹--更好的介紹ajaxsegmentfault
1. ajax對象中new XMLHttpRequest()屬性和方法列表瀏覽器
2. 經常使用事件介紹服務器
事件 | 觸發時機 |
---|---|
onreadystatechange | 當readyState的值改變時觸發,除了當它從非0變成0時 |
onloadstart | 當調用send方法時會觸發xhr.onloadstart,而後會觸發xhr.upload.onloadstart,表明開始上傳數據 |
onprogress | 上傳數據過程當中會觸發xhr.upload.onprogress,下載數據過程當中會觸發xhr.onprogress,onprogress每50ms會觸發一次 |
onabort | 調用abort方法後會觸發 |
onerror | 當發生網絡異常的時候會觸發,若是上傳數據的過程還未結束,此時會先觸發xhr.upload.onerror,而後再觸發xhr.onerror;若是上傳數據的過程已經結束,此時只會觸發xhr.onerror |
onload | 上傳數據成功,會觸發xhr.upload.onload;下載數據成功會觸發xhr.onload |
ontimeout | 當服務端響應的時間超過指定的timeout時間時,會觸發此事件 |
onloadend | 上傳數據完成(成功或者失敗)時會觸發xhr.upload.onloadend;下載數據完成(成功或失敗)會觸發 |
3. 請求開始和結束零界點網絡
【3.1】請求開始app
xhr.onloadstart
事件觸發的時候,也就是你調用xhr.send()
方法的時候。
由於xhr.open()
只是建立了一個鏈接,但並無真正開始數據的傳輸,而xhr.send()
纔是真正開始了數據的傳輸過程。只有調用了xhr.send()
,纔會觸發xhr.onloadstart
。異步
【3.2】請求結束ide
xhr.loadend
事件觸發的時候函數
備註:post
a.能夠在 send()
以後再設置此xhr.timeout
,但計時起始點仍爲調用xhr.send()
方法的時刻。
b.當xhr
爲一個sync
同步請求時,xhr.timeout
必須置爲0
,不然會拋錯。緣由能夠參考本文的【如何發一個同步請求】一節。
4. 具體實現細節--封裝ajax
function _ajax(obj){ var xhr = null; // 建立-非IE6 : IE6及其如下瀏覽器 if(window.XMLHttpRequest){ xhr=new XMLHttpRequest(); //針對某些特定版本的Mozillar瀏覽器的BUG進行修正 if(xhr.overrideMimeType) { xhr.overrideMimeType("text/xml"); } }else if(window.ActiveXObject){ var arr = ['MSXML2.XMLHTTP', 'Microsoft.XMLHTTP']; for(var i = 0; i < arr.length; i++){ try { xhr = new ActiveXObject(arr[i]); break; }catch (e){ console.log(e); } } } // 默認是異步請求 var asyc = obj.asyc || true; var type = obj.type.toUpperCase() || "GET"; var url = obj.url; var data = obj.data || {}; console.log(objToStr(data)); //選擇發送請求方式 if(type === "GET"){ xhr.open(type,url+'?'+objToStr(data),asyc); xhr.send(); }else if(type === "POST"){ xhr.open(type,url,asyc); // 告訴後臺傳的是什麼 xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); // xhr.setRequestHeader('Last-Modified', 'faqenfaAWASVaewfc'); xhr.send(objToStr(data)); } // 設置超時請求時間 xhr.timeout = 3000; // 發送異步回調函數 xhr.onreadystatechange = function () { console.log(xhr.readyState); // 測試追蹤ajax處於那種狀態,在正式代碼中要隱藏此switch switch (xhr.readyState){ case 0: console.log('xhr對象被成功構造,open()方法還未被調用'); break; case 1: console.log('open()方法已被成功調用,send()方法還未被調用'); break; case 2: console.log('send()方法已經被調用, 響應頭和響應狀態已經返回'); break; case 3: console.log('響應體(response entity body)正在下載中,此狀態下經過xhr.response可能已經有了響應數據'); break; case 4: console.log('整個數據傳輸過程結束,無論本次請求是成功仍是失敗'); break; } if(xhr.readyState === 4 && xhr.status === 200){ obj.success(xhr.responseText) }else { obj.error && obj.error(); } }; // 請求開始 xhr.onloadstart = function (e) { console.log(e,'start'); }; //ajax請求結束 xhr.loadend = function (e) { console.log(e,'end'); }; // 超時函數處理 xhr.ontimeout = function (e) { obj.timeout && obj.timeout(); console.log(e,'timeout'); }; // ajax請求錯誤處理 xhr.onerror = function (e) { obj.errorAsyc && obj.errorAsyc(); console.log(e,'error'); }; // 上傳進度處理--upload用於在數據傳輸到服務器時收集一些傳輸信息,好比上傳了多少字節,總共多少字節等,其裏面還包含了一些事件回調 xhr.upload.onprogress = function (e) { obj.progress && obj.progress(); console.log(e,'progress'); }; console.log(xhr.getAllResponseHeaders(),'0000'); // 把對象轉換成字符串 function objToStr(obj) { var arr = []; for(var key in obj){ arr.push(key+'='+obj[key]) } return arr.join('&'); } }
【封裝ajax調用方式】
window.onload = function () { btn.onclick= function () { _ajax({ url:'http://localhost:8800', type:'post', asyc:true, //默認是true data:{ username:'zhange', password:'123456' }, success:function (data) { console.log(data); }, error:function () { } }); } };