代碼以下ajax
class AJAX { constructor({url = "",method = "GET",data = {},async = true,success,error,resType = "",headers = {}},time = 5000) { //集中管理傳遞過來的參數 this.option = {url,method,data,async,success,error,resType,headers,time}; this.timeout; this.xhr = new XMLHttpRequest(); this.start(); } start() { //數據校驗 this.checkOption(); //數據格式的統一 this.initOption(); //創建鏈接 this.open(); //設置請求頭 this.setHeaders(); //設置返回數據格式 this.setResponseType(); //發送數據 this.sendData() //返回成功或失敗 this.responseData(); }; }
代碼以下json
checkOption() { let {url,async,resType,headers,time} = this.option; if (url === '') { throw new Error('請求地址不能爲空'); //打印錯誤信息,並中止當前進程 //Console.error('請求地址爲空'); 也能夠打印錯誤信息,可是不能中止當前進程 } if(typeof headers !== 'object'){ throw new Error('設置請求頭時請傳入 {key:value,key:value...} 的格式'); } if(typeof resType !== 'string'){ throw new Error('設置返回數據格式時請傳入字符出串格式'); } if(typeof time !== 'number'){ throw new Error('超時時間請傳入數字類型數據'); } if (typeof url !== 'string') { //輸出警告信息 console.warn('當前請求地址不是字符串,如今將其嘗試轉換爲字符串'); } if (async === false && resType != '') { console.warn('若是設置了請求方式爲同步,即便設置了返回數據格式也不會生效'); } };
須要注意的是返回數據格式能夠設置這幾個值,以後會寫一個詳細的傳參指南api
initOption() { let {url,async,method} = this.option; //url不是字符串轉換成字符串 if (typeof url !== 'string') { try { this.option.url = url.toString(); console.log(`轉換成功: "${this.option.url}"`); } catch (error) { throw new Error('url 轉換字符串失敗'); } } //async不是布爾型轉成布爾型 if(typeof async !=='boolean'){ async == true ? this.option.async = true : this.option.async = false; } //將 post get 轉換爲大寫 this.option.method = method.toUpperCase(); //post和get數據初始化 if(this.option.method != 'FORMDATA'){// [1] let data = this.option.data; if(typeof data === 'object'){//[2] if( this.option.method === 'GET'){ let arr=[]; for(let name in data){ arr.push(`${name}=${data[name]}`);//[3] } let strData=arr.join('&');//[4] this.option.data=`?${strData}`;//[5] }else if( this.option.method === 'POST'){ let formData = new FormData();//[6] for(let key in data){ formData.append(`${key}`,`${data[key]}`); } this.option.data=formData; } }else if(typeof data === 'string' && this.option.method === 'GET'){//[7] this.option.data=`?${data}`; } } };
通過以前的數據處理這裏只須要判斷下是 GET 仍是其餘方式(post formdata),而後選擇對應的鏈接方式promise
open(){ let {method,url,async,data} = this.option; if(method === 'GET'){ this.xhr.open(method,url+data,async); }else{ this.xhr.open(method,url,async); } }
將傳入的參數進行解析,而後設置自定義請求頭
代碼以下cookie
setHeaders(){ let headers = this.option.headers; for(let key in headers){ this.xhr.setRequestHeader(`${key.toString()}`,`${headers[key].toString()}`) } }
setResponseType() { if (this.option.async) { this.xhr.responseType = this.option.resType; } }
sendData(){ if(this.option.method == 'GET'){ this.xhr.send(); }else{ this.xhr.send(this.option.data); } this.timeout = setTimeout(()=>{ typeof this.option.error === 'function' && this.option.error('請求超時,默認超時時間爲 5000 毫秒'); this.option.reject('請求超時,默認超時時間爲 5000 毫秒'); }, this.option.time); }
判斷 success 以及 error 是否是函數,是的話會將數據返回給 success 或者將錯誤信息返回給 errorapp
responseData(){ this.xhr.onload = ()=>{ if(this.xhr.status >= 200 && this.xhr.status < 300 || this.xhr.status === 304){ typeof this.option.success === 'function' && this.option.success(this.xhr.response); }else{ typeof this.option.error === 'function' && this.option.error(this.xhr.statusText); } } }
在實現基本功能後,忽然想到 jQuery 的 ajax 是會返回一個 promise 對象,能夠同時使用回掉函數,或者使用 then 和 catch 來處理數據
所以修改了下傳入參數,以及返回數據的處理異步
傳參時代碼以下async
//add resolve reject class AJAX { constructor({url = "",method = "GET",data = {},async = true,success,error,resType = "",headers = {},resolve,reject}) { this.option = {url,method,data,async,success,error,resType,headers,resolve,reject}; this.xhr = new XMLHttpRequest(); this.start(); } }
返回數據時代碼以下函數
responseData(){ this.xhr.onload = ()=>{ if(this.xhr.status >= 200 && this.xhr.status < 300 || this.xhr.status === 304){ clearTimeout(this.timeout); typeof this.option.success === 'function' && this.option.success(this.xhr.response); this.option.resolve(this.xhr.response);//add }else{ clearTimeout(this.timeout); typeof this.option.error === 'function' && this.option.error(this.xhr.statusText); this.option.reject(this.xhr.statusText);//add } } }
class AJAX { constructor({url = "",method = "GET",data = {},async = true,success,error,resType = "",headers = {},resolve,reject}) { this.option = {url,method,data,async,success,error,resType,headers,resolve,reject}; this.xhr = new XMLHttpRequest(); this.start(); } start() { //數據校驗 this.checkOption(); //數據格式的統一 this.initOption(); //創建鏈接 this.open(); //設置請求頭 this.setHeaders(); //設置返回數據格式 this.setResponseType(); //發送數據 this.sendData() //返回成功或失敗 this.responseData(); }; checkOption() { let {url,async,resType,headers} = this.option; if (url === '') { throw new Error('請求地址不能爲空'); //打印錯誤信息,並中止當前進程 //Console.error('請求地址爲空'); 也能夠打印錯誤信息,可是不能中止當前進程 } if(typeof headers !== 'object'){ throw new Error('設置請求頭時請傳入 {key:value,key:value...} 的格式'); } if(typeof time !== 'number'){ throw new Error('超時時間請傳入數字類型數據'); } if(typeof resType !== 'string'){ throw new Error('設置返回數據格式時請傳入字符出串格式'); } // "" 與設置爲"text"相同, 是默認類型 (其實是 DOMString) // "arraybuffer" 將接收到的數據類型視爲一個包含二進制數據的 JavaScript ArrayBuffer // "blob" 將接收到的數據類型視爲一個包含二進制數據的 Blob 對象 // "document" 將接收到的數據類型視爲一個 HTML Document 或 XML XMLDocument ,這取決於接收到的數據的 MIME 類型 // "json" 將接收到的數據類型視爲 JSON 解析獲得的 // "text" 將接收到的數據類型視爲包含在 DOMString 對象中的文本 if (typeof url !== 'string') { //輸出警告信息 console.warn('當前請求地址不是字符串,如今將其嘗試轉換爲字符串'); } if (async === false && resType != '') { console.warn('若是設置了請求方式爲同步,即便設置了返回數據格式也不會生效'); } }; initOption() { let {url,async,method} = this.option; //url不是字符串轉換成字符串 if (typeof url !== 'string') { try { this.option.url = url.toString(); console.log(`轉換成功: "${this.option.url}"`); } catch (error) { throw new Error('url 轉換字符串失敗'); } } //async不是布爾型轉成布爾型 if(typeof async !=='boolean'){ async == true ? this.option.async = true : this.option.async = false; } //將 post get 轉換爲大寫 this.option.method = method.toUpperCase(); //post和get數據初始化 if(this.option.method != 'FORMDATA'){ let data = this.option.data; if(typeof data === 'object'){ if( this.option.method === 'GET'){ let arr=[]; for(let name in data){ arr.push(`${name}=${data[name]}`); } let strData=arr.join('&'); this.option.data=`?${strData}`; }else if( this.option.method === 'POST'){ let formData = new FormData(); for(let key in data){ formData.append(`${key}`,`${data[key]}`); } this.option.data=formData; } }else if(typeof data === 'string' && this.option.method === 'GET'){ this.option.data=`?${data}`; } } }; open(){ let {method,url,async,data} = this.option; if(method === 'GET'){ this.xhr.open(method,url+data,async); }else{ this.xhr.open(method,url,async); } } setHeaders(){ let headers = this.option.headers; for(let key in headers){ this.xhr.setRequestHeader(`${key.toString()}`,`${headers[key].toString()}`) } } setResponseType() { if (this.option.async) { this.xhr.responseType = this.option.resType; } } sendData(){ if(this.option.method == 'GET'){ this.xhr.send(); }else{ this.xhr.send(this.option.data); } this.timeout = setTimeout(()=>{ typeof this.option.error === 'function' && this.option.error('請求超時,默認超時時間爲 5000 毫秒'); this.option.reject('請求超時,默認超時時間爲 5000 毫秒'); }, this.option.time); } responseData(){ this.xhr.onload = ()=>{ if(this.xhr.status >= 200 && this.xhr.status < 300 || this.xhr.status === 304){ clearTimeout(this.timeout); typeof this.option.success === 'function' && this.option.success(this.xhr.response); this.option.resolve(this.xhr.response);//add }else{ clearTimeout(this.timeout); typeof this.option.error === 'function' && this.option.error(this.xhr.statusText); this.option.reject(this.xhr.statusText);//add } } } all(promises) { return Promise.all(promises); }; } function ajax({url,method,data,async,success,error,resType,headers,time}){ return new Promise((resolve, reject) => { return new AJAX({url,method,data,async,success,error,resType,headers,time,resolve,reject}); }); }
使用時能夠將代碼複製粘貼到單獨的 js 文件而後用 script 標籤引入
也能夠添加一行 export 代碼將最後的 ajax 暴露出去 使用import 引入 post
具體使用方法用法
ajax({ url:'api/login', method:'post',//支持 GET POST 和我自定義的 FORMDATA ,傳入時不區分大小寫 data = { name:"yhtx", id:"1997" },//除了這種還支持字符串 "name=yhtx&id=1997";以及 formData 數據,在傳入formData 數據時請將 method 設置爲 FORMDATA async = true,//可使用數字 1 代替 true ,數字 0 代替 false time = 5000,//請求超時時間,默認爲 5000 毫秒 success(res){ //可使用回調的形式處理數據也可使用 then },error(err){ //可使用回調的形式處理錯誤也可使用 catch }, resType = "",//能夠傳入 "" "arraybuffer" "blob" "document" "json" "text" headers = { mycookie: "46afqwiocibQEIJfa498./&678" //使用對象的方式傳參 } }).then((res)=>{ //可使用 then 的形式處理數據也可使用回調函數 }).catch((err)=>{ //可使用 catch 的形式處理數據也可使用回調函數 })