javascript fetch api怎么用_比ajax好在哪里【教程】

fetch 是原生替代 XMLHttpRequest 的现代方案,其设计取舍导致默认不带 cookie、不 reject HTTP 错误、无上传进度、不自动序列化/解析数据,需显式配置 credentials、手动检查 response.ok、用 AbortController 控制超时等。

fetch API 不是“比 AJAX 好”,而是原生替代 XMLHttpRequest 的现代方案;它默认不带 cookie、不自动解析 JSON、不 reject 网络错误——这些不是缺陷,是设计取舍,用错才觉得“不好用”。

为什么 fetch 不会自动带上 cookie

这是最常踩的坑:发请求时服务端收不到 session 或登录态,浏览器控制台却没报错。

  • fetch 默认的 credentials 模式是 'omit',即完全不发 cookie
  • 要发 cookie,必须显式写 { credentials: 'include' }(跨域时后端还需配 Access-Control-Allow-Credentials: true
  • 如果只对同域请求需要 cookie,用 'same-origin' 更安全
fetch('/api/user', {
  credentials: 'include'
})

fetch 返回 Promise 却不 reject 网络失败

很多人以为 404、500 会进 catch,结果发现 thenresponse.ok 是 false,但代码已往下跑了。

  • fetch 只在网络层彻底失败(如 DNS 错、断网、CORS 被拦)时 reject
  • HTTP 状态码 4xx/5xx 仍算“成功响应”,response.ok === false,需手动检查
  • 建议封装一层:遇到非 2xx 状态码主动 throw new Error()
fetch('/api/data')
  .then(r => {
    if (!r.ok) throw new Error(`HTTP ${r.status}`);
    return r.json();
  })
  .catch(err => console.erro

r(err));

fetch 没有 progress 回调,上传大文件怎么办

如果要做上传进度条,fetch 本身不提供上传过程中的字节监听能力。

  • 浏览器原生支持的是 XMLHttpRequest.upload.onprogressfetch 没等效 API
  • 可行解:用 ReadableStream + TransformStream 手动分块读取并上报进度(Chrome 109+ 支持)
  • 更现实的做法:小项目继续用 XMLHttpRequest 上传;大项目用 axios 或封装好的上传库

和 jQuery.ajax 相比,fetch 缺少哪些“方便但隐式”的行为

不是 fetch 不够好,而是它不替你做判断:

  • 不自动序列化 data:传对象要自己 JSON.stringify(),还要设 Content-Type: application/json
  • 不自动解析响应体:即使后端返回 JSON,也要显式调 response.json()
  • 不支持超时:需用 AbortController 配合 signal 实现
  • 不合并 headers:多次 set 同个 header 会覆盖,不是追加
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);

fetch('/api/long', {
  signal: controller.signal
}).catch(err => {
  if (err.name === 'AbortError') console.log('timeout');
});

真正难的不是写 fetch,是理解它不帮你兜底——每个环节都得自己声明意图。习惯后反而更可控;想省事就别硬套,该用 axios 还是用。