Skip to content

fetch发送请求

Fetch API 完全手册

fetch 是现代 JavaScript 中用于发起网络请求的标准 API

基本语法

fetch(url [, options])
  .then(response => {
    // 处理响应
    if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);
    return response.json(); // 或 response.text()/blob()/formData()
  })
  .then(data => {
    // 使用解析后的数据
  })
  .catch(error => {
    // 处理错误
  });

核心参数

1. url

请求的目标 URL,可以是绝对路径或相对路径。

2. options(可选)

配置请求的对象,常见属性:

{
  method: 'GET',          // HTTP 方法 (GET, POST, PUT, DELETE, etc.)
  headers: {              // 请求头
    'Content-Type': 'application/json',
    'Authorization': 'Bearer token'
  },
  body: JSON.stringify(data), // 请求体(GET 请求不能有 body)
  mode: 'cors',               // 请求模式 (cors, no-cors, same-origin)
  credentials: 'same-origin', // 携带凭证 (omit, same-origin, include)
  cache: 'default',           // 缓存策略
  redirect: 'follow',         // 重定向处理
  referrer: 'client',         // 引用来源
  signal: AbortSignal         // 中断请求的信号
}

响应处理

fetch 返回的 response 对象包含以下常用属性和方法:

属性

  • response.ok:布尔值,表示状态码是否在 200-299 之间。
  • response.status:HTTP 状态码(如 200, 404, 500)。
  • response.statusText:状态文本(如 "OK", "Not Found")。
  • response.headers:响应头(可通过 get(name) 访问)。
  • response.url:最终请求的 URL(处理重定向后)。

方法

  • response.json():解析为 JSON 对象。
  • response.text():解析为文本。
  • response.blob():解析为二进制文件。
  • response.formData():解析为 FormData 对象。
  • response.arrayBuffer():解析为 ArrayBuffer。

常见请求示例

1. GET 请求(获取 JSON 数据)

fetch('https://api.example.com/data')
  .then(res => res.json())
  .then(data => console.log(data));

2. POST 请求(发送 JSON 数据)

fetch('https://api.example.com/submit', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'John',
    age: 30
  })
})
  .then(res => res.json())
  .then(data => console.log(data));

3. 上传文件

const formData = new FormData();
formData.append('file', fileInput.files[0]);

fetch('https://api.example.com/upload', {
  method: 'POST',
  body: formData
});
fetch('https://api.example.com/data', {
  credentials: 'include' // 跨域请求也携带 Cookie
});

5. 设置自定义请求头

fetch('https://api.example.com/data', {
  headers: {
    'X-Custom-Header': 'value',
    'Authorization': 'Bearer token'
  }
});

高级用法

1. 请求超时控制

const controller = new AbortController();
const signal = controller.signal;

setTimeout(() => controller.abort(), 5000); // 5 秒后中断请求

fetch('https://api.example.com/data', { signal })
  .then(res => res.json())
  .catch(err => {
    if (err.name === 'AbortError') {
      console.log('请求超时');
    }
  });

2. 流式响应处理

fetch('https://api.example.com/large-data')
  .then(response => {
    const reader = response.body.getReader();
    const decoder = new TextDecoder();

    return reader.read().then(function processResult(result) {
      if (result.done) return;

      const chunk = decoder.decode(result.value, { stream: true });
      console.log('收到数据块:', chunk);

      return reader.read().then(processResult);
    });
  });

3. 同时处理多个请求

Promise.all([
  fetch('https://api.example.com/data1'),
  fetch('https://api.example.com/data2')
])
  .then(responses => Promise.all(responses.map(res => res.json())))
  .then(dataArray => {
    console.log('数据1:', dataArray[0]);
    console.log('数据2:', dataArray[1]);
  });

错误处理

fetch 只有在网络故障或请求被阻止时才会抛出错误,HTTP 错误(如 404、500)不会触发 catch,需要手动检查:

fetch('https://api.example.com/nonexistent')
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
    return response.json();
  })
  .catch(error => {
    console.error('请求失败:', error.message);
  });

兼容性与 Polyfill

  • 浏览器支持:Chrome 42+、Firefox 39+、Safari 10.1+、Edge 14+。
  • IE 兼容性:完全不支持,需使用 fetch polyfill

安装 polyfill:

npm install whatwg-fetch

在代码中引入:

import 'whatwg-fetch'; // 或在 HTML 中直接引入 <script src="path/to/fetch.js"></script>

常见问题

1. CORS(跨域资源共享)问题

  • 需服务器端设置正确的响应头(如 Access-Control-Allow-Origin)。
  • 使用 mode: 'no-cors' 只能获取有限的响应信息。

2. POST 请求的 Content-Type

  • 发送 JSON:'Content-Type': 'application/json' + JSON.stringify()
  • 发送表单数据:使用 FormData 对象(无需手动设置 Content-Type)。

3. 中断请求

使用 AbortController(见上文超时控制示例)。

完整示例:封装 fetch 函数

async function customFetch(url, options = {}) {
  try {
    // 设置默认选项
    const defaultOptions = {
      method: 'GET',
      headers: {
        'Accept': 'application/json'
      },
      credentials: 'same-origin',
      mode: 'cors'
    };

    // 合并选项
    const mergedOptions = { ...defaultOptions, ...options };

    // 处理 JSON 数据
    if (mergedOptions.body && typeof mergedOptions.body === 'object' && 
        !(mergedOptions.body instanceof FormData)) {
      mergedOptions.headers['Content-Type'] = 'application/json';
      mergedOptions.body = JSON.stringify(mergedOptions.body);
    }

    // 发起请求
    const response = await fetch(url, mergedOptions);

    // 检查响应状态
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }

    // 根据 Content-Type 自动解析响应
    const contentType = response.headers.get('Content-Type');
    if (contentType?.includes('application/json')) {
      return response.json();
    } else if (contentType?.includes('text/')) {
      return response.text();
    } else {
      return response.blob();
    }
  } catch (error) {
    console.error('Fetch error:', error);
    throw error;
  }
}

// 使用示例
customFetch('https://api.example.com/data')
  .then(data => console.log(data))
  .catch(err => console.error(err));