一、Promise是什么
簡單說就是一個容器,里面保存着某個未來才會結束的事件(通常是一個異步操作)的結果。
ES6規定,Promise對象是一個構造函數,用來生成Promise實例。Promise構造函數接受一個函數作為參數,該函數的兩個參數分別是resolve和reject,這兩個參數都是函數。
new Promise(function(resolve,reject){ 異步操作 ajax 定時器等{ if(結果滿意) resolve(value) else reject(error) } })
二、then方法
Promise 實例生成以后,可以用then 方法分別指定resolve和reject的回調函數。then方法可以接受兩個回調函數作為參數。第一個回調函數是Promise對象的狀態變為resolved時調用,第二個回調函數是Promise對象的狀態變為rejected時調用。其中,第二個函數是可選的,不一定要提供 。這兩個函數都接受Promise 對象傳出的值作為參數。
function timeout(ms) { return new Promise((resolve, reject) => { if(ms>=100) setTimeout(resolve, ms, 'done'); //setTimeout的第三個參數用於給第一個參數(函數)傳參
else setTimeout(reject, ms, 'error'); //setTimeout的第三個參數用於給第一個參數(函數)傳參
}); } timeout(100).then((value) => { console.log(value); //done
},(error)=>{ console.log(error) }); timeout(100).then((value) => { console.log(value); },(error)=>{ console.log(error) //error
});
三、promise中 的catch()方法
- catch方法用於指定發生錯誤時的回調
timeout(100).then((value) => { console.log(value); }.catch((error)=>{ console.log(error) });
- catch可以檢測resolve中拋出的異常
timeout(100).then((value) => { console.log(value); console.log(somethingUndefined) }).catch((error)=>{ console.log(error) //somethingUndefined is not defined
});//如果resolve中發生異常,JS不會報錯,而會把錯誤拋給catch的第一個參數
四、Promise手動封裝ajax函數
<script>
// ajax函數默認的參數
let ajaxDefaultOptions = { url: '#', // 請求地址,默認為空
method: 'GET', // 請求方式,默認為GET請求
async: true, // 請求同步還是異步,默認異步
timeout: 0, // 請求的超時時間
dataType: 'text', // 請求的數據格式,默認為text
data: null, // 請求的參數,默認為空
headers: {}, // 請求頭,默認為空
onprogress: function () {}, // 從服務器下載數據的回調
onuploadprogress: function () {}, // 處理上傳文件到服務器的回調
xhr: null // 允許函數外部創建xhr傳入,但是必須不能是使用過的
}; function _ajax(paramOptions) { //將傳入的參數和默認值合並
let options = {}; for (const key in ajaxDefaultOptions) { options[key] = ajaxDefaultOptions[key]; } // 如果傳入的是否異步與默認值相同,就使用默認值,否則使用傳入的參數
options.async = paramOptions.async === ajaxDefaultOptions.async ? ajaxDefaultOptions.async : paramOptions.async; // 判斷傳入的method是否為GET或者POST,否則傳入GET 或者可將判斷寫在promise內部,reject出去
options.method = paramOptions.method ? ("GET" || "POST") : "GET"; // 如果外部傳入xhr,否則創建一個
let xhr = options.xhr || new XMLHttpRequest(); // return promise對象
return new Promise(function (resolve, reject) { xhr.open(options.method, options.url, options.async); xhr.timeout = options.timeout; // 設置請求頭
for (const key in options.headers) { xhr.setRequestHeader(key, options.headers[key]); } // 注冊xhr對象事件
xhr.responseType = options.dataType;
//從服務器上下載數據每50ms觸發一次 xhr.onprogress = options.onprogress; xhr.onuploadprogress = options.onuploadprogress; // 開始注冊事件
// onloadend:請求結束,無論成功或者失敗
xhr.onloadend = function () { if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) { resolve(xhr); } else { reject({ errorType: "status_error", xhr: xhr }); } }; // 請求超時
xhr.ontimeout = function () { reject({ errorType: "timeout_error", xhr: xhr }); }
// ,服務器異常,請求錯誤
xhr.onerror = function () { reject({ errorType: "onerror", xhr: xhr }); }
// abort錯誤(未明白,只知道是三種異常中的一種)
xhr.onabort = function () { reject({ errorType: "onabort", xhr: xhr }); }
// 捕獲異常
try { xhr.send(options.data); } catch (error) { reject({ errorType: "send_error", error: error }); } }); } // 調用示例
_ajax({ url: 'http://localhost:3000/suc', async: true, onprogress: function (evt) { console.log(evt.position / evt.total); }, dataType: 'text/json' }).then( function (xhr) { console.log(xhr.response); }, function (e) { console.log(JSON.stringify(e)) }); </script>
參考文章:
https://blog.csdn.net/dkr380205984/article/details/81303171
阮一峰:https://blog.csdn.net/bangbanggangan/article/details/81102052
https://www.cnblogs.com/kazetotori/p/6037940.html
https://blog.csdn.net/weixin_42614080/article/details/90762439