知识点-fetch认识和使用

举报
林太白 发表于 2025/12/26 17:07:32 2025/12/26
【摘要】 知识点-fetch认识和使用

fetch认识和使用

1、认识Fetch

Fetch 主要被设计为替代 XMLHttpRequest(XHR)的 API

使用方法

// .then()使用
fetch(url)
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));


// 使用 async/await
async function fetchData() {
  try {
    let response = await fetch(url);
    let data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Error:', error);
  }
}

错误处理


fetch(url)
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

设计原因

(1)解决的主要问题

XMLHttpRequest 使用回调函数(callbacks)来处理异步操作,导致代码容易陷入“回调地狱”(callback hell),而且不容易进行错误处理和链式操作。 Microsoft提出,2006年标准化。

Fetch 基于 JavaScript 的 Promise,能够使用 .then()catch() 处理异步结果,或者使用 async/await,简洁、可读,易维护。Fetch由 WHATWG(Web Hypertext Application Technology Working Group)(Web 超文本应用技术工作组)正式提出的 API, 2015年正式成为标准。

(2)功能性设计

  • XMLHttpRequest 的 API 复杂,开发者需要手动设置请求头、处理请求的各种状态(如 onreadystatechange),并且需要多次调用方法来设置请求属性。
  • Fetch 提供了简洁统一接口

**(3)**跨域请求(CORS)

XMLHttpRequest 的跨域请求(CORS需要配置服务器支持 CORS

Fetch自动遵循浏览器的 CORS 策略,开发者只需要处理 CORS 请求的相关头部即可。

**(4)**灵活性

  • Fetch 支持更丰富的 HTTP 方法和请求配置,例如支持 GETPOSTPUTDELETE 等 HTTP 方法,并且能够更加灵活地配置请求头、请求体和其他选项。它还可以方便地处理 JSON、文本、Blob 和其他格式的数据。
  • XMLHttpRequest 的配置繁琐,需要手动管理每个步骤,尤其是一些复杂的请求(如带有复杂数据体的 POST 请求)处理起来较为繁琐

fetch 是浏览器原生支持的 API,用于发起 HTTP 请求。

axios 是一个基于 Promise 的库,提供了一些简化的功能和默认配置。底层是基于 XMLHttpRequest(用于浏览器环境)和 http/https 模块(用于 Node.js 环境)来进行实际的请求操作。

尽管 fetch 本身也可以完成所有 axios 的功能,但 axios 提供了更为便捷的功能,如自动转换 JSON 数据、请求/响应拦截器、取消请求等。

在项目中使用 fetch 代替 axios,可以通过封装 fetch 来实现类似 axios 的功能,并在项目中统一调用

2、使用Fetch

之前我们的请求方案都是使用axios进行请求的,接下来使用Fetch来代替

🍎封装src\utils\request.ts部分

使用fetch先来替代axios部分进行正常的一个请求的封装

// src/utils/request.js
import config from '@/utils/config'; //全局配置

interface RequestParams {
  url: string;
  method?: string;
  data?: any;
  headers?: Record<string, string>;
}
// const BASE_URL = `http:${import.meta.env.VITE_BASE_IP}:${import.meta.env.VITE_BASE_PORT}/${import.meta.env.VITE_PREFIX_API}/`;
// console.log(BASE_URL,'BASE_URL');
// baseURL: config.baseURL + config.prefixAPI,

const BASE_URL = `${config.baseURL}${config.prefixAPI}`;

// BASE_URL
export default async function request({ url, method = 'GET', data = null, headers = {} }: RequestParams) {
  const defaultHeaders = {
    'Content-Type': 'application/json',
    ...headers
  };
  try {
    const response = await fetch(BASE_URL+url, {
      method,
      headers: defaultHeaders,
      body: data ? JSON.stringify(data) : null
    });

    // 如果状态码不是 2xx,则抛出错误
    if (!response.ok) {
      throw new Error(`Request failed with status: ${response.status}`);
    }

    // 解析响应的 JSON 数据
    const responseData = await response.json();
    return responseData;
  } catch (error) {
    console.error('Request Error:', error);
    throw error; // 抛出错误以供调用者处理
  }
}

🍎完善头部信息

在axios的请求之中我们头部往往需要有token信息,这里我们配置一下

token我们先从本地开始进行取出

// 从localStorage或其他地方获取token
const token = localStorage.getItem('AdminToken');

const defaultHeaders = {
  'Content-Type': 'application/json',
  // 如果token存在,添加到Authorization头
  ...(token && { Authorization: `Bearer ${token}` })
};

3、参数详情

<template>
  <div class="demo-container">
    <h2>Fetch 配置示例</h2>
    <button @click="fetchData">发起请求</button>
    <div v-if="loading" class="loading">加载中...</div>
    <div v-if="error" class="error">{{ error }}</div>
    <pre v-if="data" class="result">{{ JSON.stringify(data, null, 2) }}</pre>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const data = ref(null)
const loading = ref(false)
const error = ref(null)

const fetchData = async () => {
  try {
    loading.value = true
    error.value = null

    // Fetch 配置示例
    const response = await fetch('https://api.example.com/data', {
      // 请求方法
      method: 'GET', // 'GET', 'POST', 'PUT', 'DELETE', 'PATCH' 等
      
      // 请求头
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer your-token',
        'Accept': 'application/json',
        'X-Custom-Header': 'value',
        // 可以添加任意自定义头部
      },
      
      // 请求体
      body: JSON.stringify({
        key: 'value',
        // 请求体数据
      }),
      
      // 模式
      mode: 'cors', // 'cors', 'no-cors', 'same-origin'
      
      // 凭证
      credentials: 'include', // 'include', 'same-origin', 'omit'
      
      // 缓存
      cache: 'default', // 'default', 'no-store', 'reload', 'no-cache', 'force-cache', 'only-if-cached'
      
      // 重定向
      redirect: 'follow', // 'follow', 'error', 'manual'
      
      // 引用策略
      referrer: 'no-referrer', // 'no-referrer', 'client', 或 URL
      
      // 引用策略
      referrerPolicy: 'no-referrer-when-downgrade',
      
      // 完整性
      integrity: 'sha256-abcdef1234567890',
      
      // 保持连接
      keepalive: true,
      
      // 信号
      signal: new AbortController().signal,
      
      // 优先级(实验性功能)
      priority: 'high', // 'high', 'low', 'auto'
    })

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

    // 解析响应
    const result = await response.json() // 或 response.text(), response.blob(), response.arrayBuffer()
    data.value = result

  } catch (e) {
    error.value = e.message
    console.error('Fetch error:', e)
  } finally {
    loading.value = false
  }
}
</script>

<style scoped>
.demo-container {
  max-width: 800px;
  margin: 20px auto;
  padding: 20px;
}

button {
  padding: 10px 20px;
  margin-bottom: 20px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

button:hover {
  background-color: #45a049;
}

.loading {
  color: #666;
  font-style: italic;
  padding: 10px;
}

.error {
  color: #ff4444;
  padding: 10px;
  background-color: #fff3f3;
  border-radius: 4px;
  margin: 10px 0;
}

.result {
  background-color: #f5f5f5;
  padding: 15px;
  border-radius: 4px;
  overflow-x: auto;
  white-space: pre-wrap;
}
</style>

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。