React Native 网络请求完全指南:从 Fetch 到 WebSocket

现代移动应用几乎都需要与服务器进行交互,无论是向 REST API 发送 POST 请求,还是从远程服务器加载静态资源。React Native 提供了丰富的 API 来满足这些网络需求。

一、 核心工具:Fetch API

React Native 内置了 Fetch API ,这是处理网络请求的首选方式。如果你曾在 Web 前端开发中使用过 fetchXMLHttpRequest,你会发现它非常熟悉。

1. 发起请求 (Making requests)

最简单的 GET 请求:

要从任意 URL 获取内容,只需将 URL 传递给 fetch:

TypeScript 复制代码
fetch('https://mywebsite.com/mydata.json');

自定义请求 (POST, Headers):

fetch 接受可选的第二个参数,用于定制 HTTP 请求。你可以指定额外的 Headers 或将请求方法改为 POST:

TypeScript 复制代码
fetch('https://mywebsite.com/endpoint/', {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    firstParam: 'yourValue',
    secondParam: 'yourOtherValue',
  }),
});

2. 处理响应 (Handling the response)

网络请求本质上是异步 的。Fetch 方法会返回一个 Promise,这使得异步代码的编写变得非常直观。

方式一:使用 Promise 链 (.then)

TypeScript 复制代码
const getMoviesFromApi = () => {
  return fetch('https://reactnative.dev/movies.json')
    .then(response => response.json()) // 将响应解析为 JSON
    .then(json => {
      return json.movies;
    })
    .catch(error => {
      console.error(error); // 别忘了捕获错误!
    });
};

方式二:使用 Async / Await (推荐)

这种语法让异步代码看起来更像同步代码,逻辑更清晰:

TypeScript 复制代码
const getMoviesFromApiAsync = async () => {
  try {
    const response = await fetch('https://reactnative.dev/movies.json');
    const json = await response.json();
    return json.movies;
  } catch (error) {
    console.error(error); // 如果不捕获,错误会被静默丢弃
  }
};

二、 安全限制:HTTP vs HTTPS

在移动端开发中,网络安全性受到了严格的限制,如果你试图请求非加密的 http:// 链接,可能会遭遇失败。

1. iOS: App Transport Security (ATS)

iOS 9.0 及以上版本默认开启 ATS,强制要求所有 HTTP 连接使用 HTTPS。

  • 解决办法: 如果你需要请求明文 URL(http 开头),你必须在 Info.plist 文件中添加 ATS 异常配置。
  • 注意: 苹果 App Store 审核要求对禁用 ATS 提供合理的理由。如果可能,尽量只针对特定域名开启例外,而不是完全禁用 ATS。

2. Android: Cleartext Traffic

从 Android API Level 28 (Android 9) 开始,明文流量(Cleartext traffic)默认也被阻止。

  • 解决办法: 如果必须使用 http,需在 AndroidManifest.xml 中设置 android:usesCleartextTraffic="true"

三、 第三方库与 XMLHttpRequest

React Native 内置了 XMLHttpRequest API。这意味着:

  1. 你可以直接使用 XMLHttpRequest 对象编写原生风格的请求代码。
  2. 更重要的是: 你可以使用依赖于此 API 的第三方流行库,例如 AxiosFrisbee
TypeScript 复制代码
// 原生 XMLHttpRequest 示例
const request = new XMLHttpRequest();
request.onreadystatechange = e => {
  if (request.readyState !== 4) return;
  if (request.status === 200) {
    console.log('success', request.responseText);
  } else {
    console.warn('error');
  }
};
request.open('GET', 'https://mywebsite.com/endpoint/');
request.send();

⚠️ 警告:

原生应用中没有浏览器的 CORS (跨域资源共享) 概念。因此,你在 Web 开发中遇到的跨域问题在 React Native 中通常不存在。


四、 实时通信:WebSocket

React Native 支持 WebSocket 协议,允许通过单个 TCP 连接进行全双工通信,非常适合聊天应用或实时数据推送。

TypeScript 复制代码
const ws = new WebSocket('ws://host.com/path');

ws.onopen = () => {
  // 连接已打开
  ws.send('something'); 
};

ws.onmessage = e => {
  // 收到消息
  console.log(e.data);
};

ws.onerror = e => {
  // 发生错误
  console.log(e.message);
};

ws.onclose = e => {
  // 连接关闭
  console.log(e.code, e.reason);
};

五、 已知问题与坑 (Known Issues)

在使用 fetch 时,有一些已知的局限性需要注意:

  1. 不受支持的选项: redirect: manualcredentials: omit 目前在 React Native 中不生效。

  2. Android Header 问题: 如果存在同名的 Header,Android 端只会保留最后一个。

  3. Cookie 认证不稳定:

    • 基于 Cookie 的认证目前不够稳定。
    • 在 iOS 上,如果服务器返回 302 重定向并且包含 Set-Cookie,Cookie 可能无法正确设置。由于无法手动处理重定向,这可能导致会话过期时的无限重定向循环。

六、 进阶:iOS NSURLSession 配置

对于某些高级应用,你可能需要自定义 iOS 底层的 NSURLSession(例如设置全局 User Agent 或配置临时会话)。React Native 提供了 RCTSetCustomNSURLSessionConfigurationProvider 来实现这一点。

这需要编写原生 Objective-C 代码,通常在 AppDelegate.mdidFinishLaunchingWithOptions 方法中调用:

Objective-C 复制代码
#import <React/RCTHTTPRequestHandler.h>

-(void)application:(__unused UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  
  // 设置自定义 NSURLSession 配置
  RCTSetCustomNSURLSessionConfigurationProvider(^NSURLSessionConfiguration *{
     NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
     // 在这里配置 session,例如设置 HTTPAdditionalHeaders
     return configuration;
  });

  // ... 启动 React Native
}
相关推荐
止观止12 小时前
不止解构:深入掌握 ES6+ 对象与函数的高级语法糖
前端·javascript·es6
C_心欲无痕12 小时前
react - useTransition标记低优先级更新
前端·react.js·前端框架
捻tua馔...12 小时前
antd3的表单实现(HOC解决方案)
前端·javascript·react.js
支付宝体验科技12 小时前
支付宝 KJS Compose 动态化方案与架构设计
前端·客户端
AllinLin13 小时前
JS中的call apply bind全面解析
前端·javascript·vue.js
阿乐去买菜13 小时前
2025 年末 TypeScript 趋势洞察:AI Agent 与 TS 7.0 的原生化革命
前端
海绵宝龙13 小时前
Vue 中的 Diff 算法
前端·vue.js·算法
miao_zz13 小时前
FlipperKit报错
react native
浩泽学编程13 小时前
内网开发?系统环境变量无权限配置?快速解决使用其他版本node.js
前端·vue.js·vscode·node.js·js
狗哥哥13 小时前
Vue 3 插件系统重构实战:从过度设计到精简高效
前端·vue.js·架构