xhr
想要设置进度条我们就必须知道当前请求已经加载的数据量。根据当前数据量/总数据量 *100就是百分比,而XMLHttpRequest提供了事件。
fetch
fetch给了我们可读流实时获取当前的数据量。可读对象的read方法返回promise,我们可以通过其获取{value,done}类似一迭代器的结果。而value的长度就是数据量
class FetchRequest{
constructor() {
this.baseURL = 'http://127.0.0.1:3000'
}
request(url,method,data,cb) {
return new Promise(async(resolve, reject) => {
const res = await window.fetch(this.baseURL+url, {
method,
body:data
})
const total = res.headers.get('content-length')
const reader = res.body.getReader()//创建可读流
let loaded = 0
while (true) {
const { done, value } = await reader.read()
loaded += value?.length || 0
const progress = loaded / total * 100
cb && cb()
if (done) {
break;
}
}
})
}
}
class XHRRequest {
xhr = new XMLHttpRequest()
constructor(options) {
this.baseURL = options.baseURL
options.watchProgress && this.watchProgress()
this.xhr.timeout = options.timeout || 5000
}
defaultProgressCb(e) {
const progress = document.querySelector('.progress')
progress.textContent = e.loaded / e.total * 100 + '%'
if (progress.textContent.includes('100')) {
setTimeout(() => {
progress.style.display = 'none'
}, 1000);
}
}
watchProgress(cb) {
this.xhr.addEventListener("progress", (e) => {
cb && cb() || this.defaultProgressCb(e)
});
}
closeWatchProgress() {
this.xhr.removeEventListener('progress')
}
request(method = 'GET', url) {
return new Promise((resolve, reject) => {
this.xhr.open(method.toLocaleUpperCase(), this.baseURL + url)
method.toLocaleUpperCase() === 'POST' &&
this.xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
this.xhr.send()
this.xhr.onreadystatechange = () => {
if (this.xhr.readystate === this.xhr.DONE && this.xhr.status === 200) {
resolve(this.xhr.responseText)
}
reject(this.xhr.statusText)
}
})
}
}