const xhr = new XMLHttpRequest();// progress eventxhr.upload.onprogress = (p) => {console.log(Math.round((p.loaded / p.total) * 100) + "%");};
事件处理程序传递的对象有三个属性:
- lengthComputable —— 如果进度可以计算,则设置为 true
- total —— 消息体的工作总量或内容长度
- loaded —— 到目前为止完成的工作或内容的数量
超时支持
XMLHttpRequest 对象提供了一个 timeout 属性,可以将其设置为请求自动终止前允许运行的毫秒数;如果超时,就触发一个 timeout 事件来处理:
const xhr = new XMLHttpRequest();xhr.timeout = 5000; // 5-second maximumxhr.ontimeout = () => console.log("timeout");
fetch() 中可以封装一个函数来实现超时功能:function fetchTimeout(url, init, timeout = 5000) {return new Promise((resolve, reject) => {fetch(url, init).then(resolve).catch(reject);setTimeout(reject, timeout);});}
或者,你可以使用 Promise.race():Promise.race([fetch("/service", { method: "GET" }),new Promise((resolve) => setTimeout(resolve, 5000)),]).then((res) => console.log(res));
这两个方法都不容易使用,另外请求将在后台继续运行 。中止支持
运行中的请求可以通过 XMLHttpRequest 的 abort() 方法取消,如有必要,可以附加一个 abort 事件来处理:
const xhr = new XMLHttpRequest();xhr.open("GET", "/service");xhr.send();// ...xhr.onabort = () => console.log("aborted");xhr.abort();
你可以中止一个 fetch(),但它不是那么直接,需要一个 AbortController 对象:const controller = new AbortController();fetch("/service", {method: "GET",signal: controller.signal,}).then((res) => res.json()).then((json) => console.log(json)).catch((error) => console.error("Error:", error));// abort requestcontroller.abort();
当 fetch() 中止时,catch() 块执行 。更显式的故障检测
当开发人员第一次使用 fetch() 时,假设一个 HTTP 错误,如 404 Not Found 或 500 Internal Server error 将触发 Promise 拒绝并运行相关的 catch() 块,这似乎是合乎逻辑的,但事实并非如此:Promise 成功地解决了这些响应,只有当网络没有响应或请求被中断时,才会发生拒绝 。
fetch() 的 Response 对象提供了 status 和 ok 属性,但并不总是显式地需要检查它们,XMLHttpRequest 更明确,因为单个回调函数处理每一个结果:你应该在每个示例中都看到 stuatus 检查 。
浏览器支持
我希望你不必支持 Internet Explorer 或 2015 年之前的浏览器版本,但如果是这样的话,XMLHttpRequest 是你唯一的选择 。XMLHttpRequest 也很稳定的,API 不太可能更新 。Fetch 比较新,还缺少几个关键特性,虽然更新不太可能破坏代码,但你可以期待一些维护 。
应该使用哪个 API ?
大多数开发人员都会使用更新的 Fetch API,它的语法更简洁,比 XMLHttpRequest 更有优势;也就是说,这些好处中的许多都有特定的用例,但在大多数应用程序中都不需要它们 。只有两种情况下 XMLHttpRequest 仍必不可少:
- 你正在支持非常老的浏览器——这种需求会随着时间的推移而下降 。
- 你需要显示上传进度条 。Fetch 后续将会支持,但可能需要几年的时间 。
推荐阅读
- 忽必烈灭宋之战?忽必烈灭宋之战
- 如果刘备打赢了夷陵之战?刘备为什么发动夷陵之战-
- 如果刘备打赢了夷陵之战?打败关羽的是不是陆逊
- 《金铲铲之战》阵容推荐怎么设置?
- 小程序的“中局之战”
- 《金铲铲之战》冷门上分阵容有哪些推荐?
- 为曹操解了樊城之围?樊城之战抵抗关羽
- 汉中之战曹操为什么败了 汉中刘备战胜曹操的原因
- 曹操为什么在赤壁之战中败得一塌糊涂 历史上赤壁之战曹操失败的真实原因
- 刘备携带百姓渡江是哪个江,曹操为什么能在官渡之战取胜