一、Fetch API简介

基本语法

二、基本GET请求

2.1 最简单的GET请求

2.2 带参数的GET请求

三、POST请求与数据提交

3.1 提交JSON数据

3.2 提交表单数据

四、请求配置选项

4.1 完整的配置选项

五、响应处理

5.1 响应状态检查

5.2 处理不同的响应类型

六、错误处理

6.1 完整的错误处理方案

七、超时处理

7.1 实现请求超时

八、封装实用的Fetch工具函数

8.1 完整的请求封装

九、React Native中的特殊考虑

9.1 处理网络状态变化

9.2 图片下载示例

十、最佳实践与性能优化

10.1 请求缓存策略

10.2 请求取消

总结

引用文章和出处


在React Native开发中,网络请求是必不可少的功能。Fetch API作为现代JavaScript的标准网络请求方式,在React Native中得到了完美的支持。本文将详细介绍Fetch API的完整使用方法,帮助开发者掌握这一重要的网络请求技术。

一、Fetch API简介

Fetch API提供了一个全局的fetch()方法,用于发起网络请求。它基于Promise设计,相比传统的XMLHttpRequest更加简洁和强大。

基本语法

fetch(url, options)
  .then(response => {
    // 处理响应
  })
  .catch(error => {
    // 处理错误
  });

二、基本GET请求

2.1 最简单的GET请求

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => {
    console.log('获取到的数据:', data);
  })
  .catch(error => {
    console.error('请求失败:', error);
  });

2.2 带参数的GET请求

const queryParams = new URLSearchParams({
  page: 1,
  limit: 10,
  keyword: 'react'
});

fetch(`https://api.example.com/data?${queryParams}`)
  .then(response => response.json())
  .then(data => console.log(data));

三、POST请求与数据提交

3.1 提交JSON数据

fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer your-token'
  },
  body: JSON.stringify({
    name: '张三',
    email: 'zhangsan@example.com'
  })
})
.then(response => response.json())
.then(data => console.log('创建成功:', data));

3.2 提交表单数据

const formData = new FormData();
formData.append('username', 'testuser');
formData.append('avatar', {
  uri: 'path/to/image.jpg',
  type: 'image/jpeg',
  name: 'avatar.jpg'
});

fetch('https://api.example.com/upload', {
  method: 'POST',
  headers: {
    'Content-Type': 'multipart/form-data',
  },
  body: formData
});

四、请求配置选项

4.1 完整的配置选项

fetch('https://api.example.com/data', {
  method: 'GET', // POST, PUT, DELETE, PATCH
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer token',
    'X-Custom-Header': 'value'
  },
  body: JSON.stringify(data), // 请求体数据
  timeout: 10000, // 超时时间(需要polyfill)
  credentials: 'include', // 包含cookie
  cache: 'no-cache', // 缓存策略
  redirect: 'follow' // 重定向策略
});

五、响应处理

5.1 响应状态检查

fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP错误! 状态码: ${response.status}`);
    }
    return response.json();
  })
  .then(data => console.log(data))
  .catch(error => console.error('请求失败:', error));

5.2 处理不同的响应类型

fetch('https://api.example.com/data')
  .then(response => {
    const contentType = response.headers.get('content-type');
    
    if (contentType.includes('application/json')) {
      return response.json();
    } else if (contentType.includes('text/html')) {
      return response.text();
    } else if (contentType.includes('image/')) {
      return response.blob();
    } else {
      return response.text();
    }
  });

六、错误处理

6.1 完整的错误处理方案

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    
    if (!response.ok) {
      throw new Error(`服务器错误: ${response.status}`);
    }
    
    const data = await response.json();
    return data;
    
  } catch (error) {
    if (error.name === 'TypeError') {
      console.error('网络连接错误:', error.message);
    } else if (error.name === 'SyntaxError') {
      console.error('JSON解析错误:', error.message);
    } else {
      console.error('其他错误:', error.message);
    }
    throw error;
  }
}

七、超时处理

7.1 实现请求超时

function fetchWithTimeout(url, options = {}, timeout = 10000) {
  return Promise.race([
    fetch(url, options),
    new Promise((_, reject) =>
      setTimeout(() => reject(new Error('请求超时')), timeout)
    )
  ]);
}

// 使用示例
fetchWithTimeout('https://api.example.com/data', {}, 5000)
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('请求失败:', error));

八、封装实用的Fetch工具函数

8.1 完整的请求封装

class ApiClient {
  constructor(baseURL, defaultOptions = {}) {
    this.baseURL = baseURL;
    this.defaultOptions = {
      headers: {
        'Content-Type': 'application/json',
      },
      ...defaultOptions
    };
  }

  async request(endpoint, options = {}) {
    const url = `${this.baseURL}${endpoint}`;
    const config = {
      ...this.defaultOptions,
      ...options,
      headers: {
        ...this.defaultOptions.headers,
        ...options.headers,
      },
    };

    try {
      const response = await fetch(url, config);
      
      if (!response.ok) {
        throw new Error(`HTTP错误 ${response.status}: ${response.statusText}`);
      }

      const contentType = response.headers.get('content-type');
      if (contentType && contentType.includes('application/json')) {
        return await response.json();
      }
      return await response.text();
      
    } catch (error) {
      console.error('API请求错误:', error);
      throw error;
    }
  }

  get(endpoint, options = {}) {
    return this.request(endpoint, { ...options, method: 'GET' });
  }

  post(endpoint, data, options = {}) {
    return this.request(endpoint, {
      ...options,
      method: 'POST',
      body: JSON.stringify(data),
    });
  }

  put(endpoint, data, options = {}) {
    return this.request(endpoint, {
      ...options,
      method: 'PUT',
      body: JSON.stringify(data),
    });
  }

  delete(endpoint, options = {}) {
    return this.request(endpoint, { ...options, method: 'DELETE' });
  }
}

// 使用示例
const api = new ApiClient('https://api.example.com');

// GET请求
api.get('/users')
  .then(users => console.log(users));

// POST请求  
api.post('/users', { name: '李四', email: 'lisi@example.com' })
  .then(user => console.log('创建的用户:', user));

九、React Native中的特殊考虑

9.1 处理网络状态变化

import { NetInfo } from '@react-native-community/netinfo';

class NetworkAwareFetch {
  static async fetchWithNetworkCheck(url, options) {
    const netInfo = await NetInfo.fetch();
    
    if (!netInfo.isConnected) {
      throw new Error('网络未连接');
    }
    
    return fetch(url, options);
  }
}

9.2 图片下载示例

async function downloadImage(url, filename) {
  try {
    const response = await fetch(url);
    const blob = await response.blob();
    
    // 保存到本地文件系统
    // 这里需要使用RN的文件系统API
    console.log('图片下载成功:', blob.size);
    
  } catch (error) {
    console.error('图片下载失败:', error);
  }
}

十、最佳实践与性能优化

10.1 请求缓存策略

const cache = new Map();

async function cachedFetch(url, options = {}) {
  if (cache.has(url)) {
    return cache.get(url);
  }
  
  const response = await fetch(url, options);
  const data = await response.json();
  
  // 缓存5分钟
  cache.set(url, data);
  setTimeout(() => cache.delete(url), 5 * 60 * 1000);
  
  return data;
}

10.2 请求取消

class CancelableFetch {
  constructor() {
    this.controller = new AbortController();
  }

  fetch(url, options = {}) {
    return fetch(url, {
      ...options,
      signal: this.controller.signal
    });
  }

  cancel() {
    this.controller.abort();
  }
}

// 使用示例
const cancelableFetch = new CancelableFetch();

// 发起请求
cancelableFetch.fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('请求已被取消');
    }
  });

// 取消请求
// cancelableFetch.cancel();

总结

Fetch API为React Native开发提供了强大而灵活的网络请求能力。通过本文的详细介绍,您应该已经掌握了:

  1. 基本的GET/POST请求使用方法
  2. 请求配置和响应处理技巧
  3. 完整的错误处理方案
  4. 实用的封装方法和最佳实践

在实际开发中,建议根据项目需求对Fetch进行适当的封装,以提高代码的可维护性和复用性。

引用文章和出处

  1. MDN Web Docs - Fetch API
  2. React Native官方文档 - 网络
  3. JavaScript.info - Fetch
  4. Google Developers - Introduction to Fetch

希望这篇指南对您的React Native开发有所帮助!如有任何问题,欢迎在评论区讨论。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐