前言
- 做web開發,我們都知道瀏覽器通過
XMLHttpRequest
對象進行http通信 - 在實際開發中我們使用的是各種框架封裝了的
XMLHttpRequest
對象,對具體實現往往一知半解.所以為了換框架好上手,請求有異常好調試,有必要深入學習一下XMLHttpRequest
- 本文從基礎
XMLHttpRequest
開始,一步步把它封裝為更實用的框架級別
實例
- 一個最簡單的http請求
let xhr = new XMLHttpRequest(); xhr.open('GET', '/url', true); xhr.send();
- 一個稍微完整的http請求
let xhr = new XMLHttpRequest(); // 請求成功回調函數 xhr.onload = e => { console.log('request success'); }; // 請求結束 xhr.onloadend = e => { console.log('request loadend'); }; // 請求出錯 xhr.onerror = e => { console.log('request error'); }; // 請求超時 xhr.ontimeout = e => { console.log('request timeout'); }; // 請求回調函數.XMLHttpRequest標准又分為Level 1和Level 2,這是Level 1和的回調處理方式 // xhr.onreadystatechange = () => { // if (xhr.readyState !== 4) { // return; // } // const status = xhr.status; // if ((status >= 200 && status < 300) || status === 304) { // console.log('request success'); // } else { // console.log('request error'); // } // }; xhr.timeout = 0; // 設置超時時間,0表示永不超時 // 初始化請求 xhr.open('GET/POST/DELETE/...', '/url', true || false); // 設置期望的返回數據類型 'json' 'text' 'document' ... xhr.responseType = ''; // 設置請求頭 xhr.setRequestHeader('', ''); // 發送請求 xhr.send(null || new FormData || 'a=1&b=2' || 'json字符串');
- 很多東西一看就懂,但當真正去用的時候就會發現很多問題
- 為了深入學習,本着使XMLHttpRequest更易用的原則,模仿jQuery ajax封裝
XMLHttpRequest
封裝XMLHttpRequest
const http = { /** * js封裝ajax請求 * >>使用new XMLHttpRequest 創建請求對象,所以不考慮低端IE瀏覽器(IE6及以下不支持XMLHttpRequest) * >>使用es6語法,如果需要在正式環境使用,則可以用babel轉換為es5語法 https://babeljs.cn/docs/setup/#installation * @param settings 請求參數模仿jQuery ajax * 調用該方法,data參數需要和請求頭Content-Type對應 * Content-Type data 描述 * application/x-www-form-urlencoded 'name=哈哈&age=12'或{name:'哈哈',age:12} 查詢字符串,用&分割 * application/json name=哈哈&age=12' json字符串 * multipart/form-data new FormData() FormData對象,當為FormData類型,不要手動設置Content-Type * 注意:請求參數如果包含日期類型.是否能請求成功需要后台接口配合 */ ajax: (settings = {}) => { // 初始化請求參數 let _s = Object.assign({ url: '', // string type: 'GET', // string 'GET' 'POST' 'DELETE' dataType: 'json', // string 期望的返回數據類型:'json' 'text' 'document' ... async: true, // boolean true:異步請求 false:同步請求 required data: null, // any 請求參數,data需要和請求頭Content-Type對應 headers: {}, // object 請求頭 timeout: 1000, // string 超時時間:0表示不設置超時 beforeSend: (xhr) => { }, success: (result, status, xhr) => { }, error: (xhr, status, error) => { }, complete: (xhr, status) => { } }, settings); // 參數驗證 if (!_s.url || !_s.type || !_s.dataType || _s.async === undefined) { alert('參數有誤'); return; } // 創建XMLHttpRequest請求對象 let xhr = new XMLHttpRequest(); // 請求開始回調函數 xhr.addEventListener('loadstart', e => { _s.beforeSend(xhr); }); // 請求成功回調函數 xhr.addEventListener('load', e => { const status = xhr.status; if ((status >= 200 && status < 300) || status === 304) { let result; if (xhr.responseType === 'text') { result = xhr.responseText; } else if (xhr.responseType === 'document') { result = xhr.responseXML; } else { result = xhr.response; } // 注意:狀態碼200表示請求發送/接受成功,不表示業務處理成功 _s.success(result, status, xhr); } else { _s.error(xhr, status, e); } }); // 請求結束 xhr.addEventListener('loadend', e => { _s.complete(xhr, xhr.status); }