你瞅啥呢

2026-05-22 fetch 与 Promise:本质区别与协同使用指南(deepseek)

fetchPromise 不是同一层级的对比对象,因为 fetch 返回的就是 Promise

更准确的对比应该是:fetchaxios/XMLHttpRequest 的区别,或者 Promiseasync/await/回调函数 的区别

核心关系

// fetch 返回一个 Promise
const promise = fetch('/api/data');  // promise 是一个 Promise 对象

// 所以可以用 .then()
promise.then(response => response.json());

// 也可以用 async/await
const response = await fetch('/api/data');

1. fetch 是什么?

fetch 是一个浏览器原生 API,用于发起网络请求。

// fetch 的基本用法
fetch('https://api.example.com/users')
  .then(response => response.json())  // 解析 JSON
  .then(data => console.log(data))
  .catch(error => console.error('请求失败:', error));

2. Promise 是什么?

Promise 是一种异步编程的语法/对象,用于处理异步操作。

// 手动创建 Promise
const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('成功');
    // 或 reject('失败');
  }, 1000);
});

myPromise.then(result => console.log(result));

3. 主要区别

维度 fetch Promise
是什么 浏览器 API(发起网络请求) JavaScript 异步编程对象
返回结果 返回 Promise 对象 返回 Promise 对象本身
主要用途 获取网络资源 处理任何异步操作
能否独立使用 是,直接调用 需要配合异步函数或手动 resolve
错误处理 网络错误会 reject,HTTP 错误(404)不 reject 通过 reject 或 throw 触发 catch

4. 代码对比

fetch 使用(内部自动创建 Promise)

// fetch 内部已经帮你创建了 Promise
fetch('/api/user')
  .then(res => res.json())
  .then(data => console.log(data))
  .catch(err => console.error(err));

手动创建 Promise(模拟 fetch)

// 你自己模拟 fetch 的实现
function myFetch(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', url);
    xhr.onload = () => resolve(xhr.response);
    xhr.onerror = () => reject('网络错误');
    xhr.send();
  });
}

// 用法和 fetch 一样
myFetch('/api/user')
  .then(data => console.log(data))
  .catch(err => console.error(err));

5. 各自的特性

fetch 的特性(作为网络请求 API)

// 1. 默认不带 cookie
fetch('/api/data', {
  credentials: 'include'  // 需要手动开启
});

// 2. 只有网络错误才 reject,HTTP 404 不会 reject
fetch('/not-found')  // 不会进 catch,而是进 then
  .then(res => {
    if (!res.ok) throw new Error('HTTP 错误');  // 需要手动处理
    return res.json();
  });

// 3. 支持请求/响应拦截(需要封装)
// 4. 支持流式处理(Response.body)

Promise 的特性(作为异步编程工具)

// 1. 链式调用
doSomething()
  .then(result => doSomethingElse(result))
  .then(finalResult => console.log(finalResult))
  .catch(error => console.error(error));

// 2. 并发处理
Promise.all([fetch('/user'), fetch('/posts')])
  .then(([user, posts]) => console.log(user, posts));

Promise.race([fetch('/fast'), fetch('/slow')])
  .then(first => console.log(first));

// 3. 状态管理
const pendingPromise = new Promise(() => {});  // pending 状态
const resolvedPromise = Promise.resolve('完成'); // resolved 状态
const rejectedPromise = Promise.reject('失败');  // rejected 状态

// 4. 错误冒泡
Promise.resolve()
  .then(() => { throw new Error('错误'); })
  .then(() => console.log('不会执行'))
  .catch(err => console.log('在这里捕获'));  // 错误会一路向下直到 catch

6. 结合使用的常见模式

// 模式1:fetch + .then() + .catch()
fetch('/api/user')
  .then(res => res.json())
  .then(data => {
    console.log('用户数据:', data);
    return fetch(`/api/posts?userId=${data.id}`);
  })
  .then(res => res.json())
  .then(posts => console.log('用户帖子:', posts))
  .catch(err => console.error('请求失败:', err));

// 模式2:fetch + async/await(推荐)
async function getUserAndPosts() {
  try {
    const userRes = await fetch('/api/user');
    const user = await userRes.json();
    
    const postsRes = await fetch(`/api/posts?userId=${user.id}`);
    const posts = await postsRes.json();
    
    console.log('用户帖子:', posts);
  } catch (error) {
    console.error('请求失败:', error);
  }
}

// 模式3:fetch + Promise.all(并发请求)
async function getMultipleResources() {
  try {
    const [users, posts, comments] = await Promise.all([
      fetch('/api/users').then(res => res.json()),
      fetch('/api/posts').then(res => res.json()),
      fetch('/api/comments').then(res => res.json())
    ]);
    console.log({ users, posts, comments });
  } catch (error) {
    console.error('某个请求失败:', error);
  }
}

7. 错误处理的关键区别

// fetch 的特殊性:网络错误才 reject
fetch('https://invalid-domain-12345.com')  // 域名不存在
  .catch(err => console.log('网络错误,会进这里'));

fetch('/api/not-exist')  // HTTP 404
  .then(res => {
    console.log('HTTP 404 也会进这里,res.ok = false');
    if (!res.ok) throw new Error('HTTP 错误');
    return res.json();
  })
  .catch(err => console.log('手动 throw 后才能进这里'));

// 普通 Promise:reject 或 throw 都会进入 catch
Promise.reject('直接 reject')
  .catch(err => console.log('会进这里'));

Promise.resolve()
  .then(() => { throw new Error('throw 错误'); })
  .catch(err => console.log('也会进这里'));

总结

如果你想... 使用...
发起网络请求获取数据 fetch()
处理异步操作(定时器、读取文件等) new Promise()
优雅地处理多个并发请求 Promise.all() / Promise.race()
让异步代码更易读 async/await(配合 Promise)
手动控制异步流程(延迟、重试等) new Promise() + resolve/reject

简单记忆:

  • fetch = 专门用来请求数据的工具(返回 Promise)
  • Promise = 处理所有异步操作的通用机制(包括 fetch 的结果)
posted @ 2026-05-22 09:19  叶乘风  阅读(17)  评论(0)    收藏  举报