前端做網(wǎng)絡(luò)請(qǐng)求是基于AJAX的,Ajax有兩種方式:
XMLHttpRequest: 簡(jiǎn)稱XHR,比較常用的axios就是基于XMLHttpRequest封裝的
fetch:新的api,它相對(duì)應(yīng)的第三方庫(kù)是umi-request
瀏覽器原生的就支持這兩種請(qǐng)求。其他庫(kù)都是基于這兩種去封裝的。

xhr_fetch.png
fetch文檔比較中可以看出來(lái),它無(wú)法實(shí)現(xiàn)請(qǐng)求進(jìn)度的監(jiān)控,因?yàn)閒etch是基于promise的,promise只有成功和失敗,所以進(jìn)度監(jiān)控是難以處理的。
XMLHttpRequest進(jìn)度監(jiān)控
function xhr_request(options={}) {
const {url, method='GET', onProgress, data=null} = options;
return new Promise(async (resolve, reject)=> {
const xhr = XMLHttpRequest();
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onreadystatechange = ()=> {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
resolve(xhr.responseText);
} else {
reject({status: xhr.status, message: '請(qǐng)求失敗'})
}
}
}
// xhr.onprogress = onProgress;
// 或
xhr.addEventListener('progress', e => {
console.log(e.loaded, e.total);
onProgress &&
onProgress({
loaded: e.loaded,
total: e.total
});
});
//監(jiān)控文件上傳的進(jìn)度
// xhr.upload.onprogress = onProgress;
// 或
xhr.upload.addEventListener('progress', onProgress);
// 建立請(qǐng)求連接
xhr.open(method, url);
// 發(fā)送請(qǐng)求,data則為請(qǐng)求參數(shù)
xhr.send(data);
});
}
fetch進(jìn)度監(jiān)控
function fetch_request(options={}) {
const {url, method='GET', onProgress, data=null} = options;
return new Promise(async (resolve)=> {
const resp = await fetch(url, {
method,
body: data
});
// 獲取總的數(shù)據(jù)量
const total = +resp.headers.get('content-length');
const decoder = new TextDecoder();
let body = '';
// 獲取數(shù)據(jù)流的讀取器
const reader = resp.body.getReader();
let loaded = 0;
while(1) {
// value是buffer類型
const {done, value} = await reader.read();
if(done) {
// 數(shù)據(jù)讀取完成則退出循環(huán)
break;
}
loaded += value.length;
// buffer解碼
body += decoder.decode(value);
onProgress && onProgress({loaded, total});
}
resolve(body);
});
}