鸿蒙应用HTTP网络请求实战指南:从基础到进阶优化

1. HTTP协议基础与鸿蒙网络架构

HTTP协议是现代应用网络通信的基石,基于客户端-服务器模型工作。在鸿蒙生态中,网络通信能力主要由NetworkKit提供,它封装了强大的HTTP客户端功能,支持所有常见的HTTP方法,包括GET、POST、PUT、DELETE等。

核心特点

  • 请求从客户端发出,服务器端响应:通信总是由客户端发起,服务器端在没有接收到请求之前不会发送响应

  • 完整的HTTP方法支持:满足RESTful API设计需求

  • 异步处理机制:基于Promise和async/await,保证UI流畅性

2. 开发前准备:权限与配置

2.1 网络权限申请

在应用的module.json5文件中添加网络访问权限:

复制代码
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ]
  }
}

这是使用HTTP功能的前提条件,没有此权限应用将无法进行任何网络访问。

2.2 HTTP明文传输配置(如需要)

如果访问的服务器使用HTTP而非HTTPS,需要在config.json中启用明文传输:

复制代码
{
  "deviceConfig": {
    "default": {
      "network": {
        "cleartextTraffic": true
      }
    }
  }
}

3. 核心实现方案:基于http模块

3.1 基础使用步骤

鸿蒙系统的@kit.NetworkKit中的http模块是进行HTTP请求的主要方式。

1. 导入模块

复制代码
import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';

2. 创建请求对象

复制代码
// 每一个httpRequest对应一个HTTP请求任务,不可复用
let httpRequest = http.createHttp();

3. 订阅响应头事件(可选)

复制代码
httpRequest.on('headersReceive', (header: Object) => {
  console.info('header: ' + JSON.stringify(header));
});

此接口会比request请求先返回,可以根据业务需要订阅此消息。

4. 发起请求并处理响应

复制代码
// 填写HTTP请求的URL地址,可以带参数也可以不带参数
httpRequest.request(
  "https://api.example.com/data",
  {
    method: http.RequestMethod.GET, // 可选,默认为http.RequestMethod.GET
    header: {
      'Content-Type': 'application/json'
    },
    readTimeout: 60000, // 可选,默认为60000ms
    connectTimeout: 60000, // 可选,默认为60000ms
  },
  (err: BusinessError, data: http.HttpResponse) => {
    if (!err) {
      // data.result为HTTP响应内容,可根据业务需要进行解析
      console.info('Result:' + JSON.stringify(data.result));
      console.info('code:' + JSON.stringify(data.responseCode));
      
      // 取消订阅HTTP响应头事件
      httpRequest.off('headersReceive');
      // 请求完成后销毁对象
      httpRequest.destroy();
    } else {
      console.error('error:' + JSON.stringify(err));
      httpRequest.off('headersReceive');
      httpRequest.destroy();
    }
  }
);

3.2 使用Promise风格

除了回调函数,http模块也支持Promise风格,使代码更简洁:

复制代码
httpRequest.request('https://hmajax.itheima.net/api/news')
  .then((data: http.HttpResponse) => {
    if (data.responseCode === http.ResponseCode.OK) {
      console.info('Result:' + data.result.toString());
      // 处理请求结果
    }
  })
  .catch((err: Error) => {
    console.error('error:' + err.message);
  })
  .finally(() => {
    httpRequest.destroy();
  });

4. 进阶功能与配置

4.1 高级请求参数

http模块提供了丰富的高级配置选项:

复制代码
httpRequest.request(
  "https://api.example.com/upload",
  {
    method: http.RequestMethod.POST,
    extraData: JSON.stringify({
      "param1": "value1",
      "param2": "value2"
    }),
    header: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer your-token-here'
    },
    usingCache: true, // 是否使用缓存
    priority: 1, // 请求优先级
    usingProtocol: http.HttpProtocol.HTTP1_1, // 使用协议
    addressFamily: http.AddressFamily.DEFAULT // 地址族
  }
);

4.2 文件上传

从API 11开始,支持multipart/form-data格式的文件上传:

复制代码
multiFormDataList: [
  {
    name: "textPart",
    contentType: 'text/plain',
    data: 'Example data',
  }, {
    name: "filePart",
    contentType: 'image/jpeg',
    filePath: `${context.filesDir}/image.jpg`,
    remoteFileName: 'image.jpg'
  }
]

4.3 安全配置

鸿蒙提供了多种安全增强选项:

复制代码
{
  // 客户端证书配置(API 11+)
  clientCert: {
    certPath: '/path/to/client.pem',
    keyPath: '/path/to/client.key',
    keyPassword: "password"
  },
  // 证书锁定(API 12+)
  certificatePinning: [
    {
      publicKeyHash: 'Pin1',
      hashAlgorithm: 'SHA-256'
    }
  ]
}

5. 异步处理最佳实践

5.1 Promise与async/await

使用async/await可以更优雅地处理异步请求:

复制代码
async function fetchData(): Promise<void> {
  try {
    const httpRequest = http.createHttp();
    const response = await httpRequest.request('https://api.example.com/data');
    
    if (response.responseCode === http.ResponseCode.OK) {
      const data = JSON.parse(response.result.toString());
      // 处理数据
      this.updateUI(data);
    }
  } catch (err) {
    console.error('请求失败:', err.message);
  } finally {
    httpRequest.destroy();
  }
}

// 使用示例
async function loadMultipleData(): Promise<void> {
  const userData = await fetchUserData();
  const productData = await fetchProductData();
  // 并行请求
  const [news, weather] = await Promise.all([
    fetchNews(),
    fetchWeather()
  ]);
}

5.2 JSON数据处理

网络请求通常涉及JSON数据的序列化和反序列化:

复制代码
// 定义数据类型
interface User {
  name: string;
  age: number;
}

// JSON字符串转对象
const userStr = '{"name":"Jack","age":18}';
const user = JSON.parse(userStr) as User;

// 对象转JSON字符串
const newUserStr = JSON.stringify(user);

// 在HTTP请求中的应用
const requestData = {
  userId: 123,
  action: 'update'
};

httpRequest.request(
  url,
  {
    method: http.RequestMethod.POST,
    extraData: JSON.stringify(requestData),
    header: {
      'Content-Type': 'application/json'
    }
  }
);

6. 网络状态管理与优化

6.1 网络状态检测

在进行网络请求前,可以先检查网络状态:

复制代码
import { connection } from '@kit.NetworkKit';

// 检查默认网络状态
const netManager = connection.getDefaultNet();
netManager.hasDefaultNet((err, data) => {
  if (!err && data) {
    // 有网络连接,发起请求
    this.fetchData();
  } else {
    // 无网络连接,显示提示
    this.showOfflineMessage();
  }
});

6.2 订阅网络状态变化

复制代码
// 订阅网络状态变化事件
netManager.on('netAvailable', (data) => {
  console.info('网络已连接');
  // 重新尝试失败的请求
  this.retryFailedRequests();
});

netManager.on('netUnavailable', () => {
  console.info('网络已断开');
  // 显示离线状态
  this.showOfflineMode();
});

7. 性能优化策略

7.1 请求优化技巧

  1. 减少不必要的数据传输

    • 只请求需要的字段

    • 使用增量更新而非全量数据

  2. 合理利用缓存

    复制代码
    {
      usingCache: true, // 启用缓存
      // 其他参数...
    }
  3. 连接复用

    • 避免频繁创建和销毁连接

    • 合理设置超时时间

7.2 智能网络切换

利用鸿蒙的网络管理功能,根据网络状况自动优化:

复制代码
// 根据网络类型调整请求策略
private adjustRequestStrategy(netType: connection.NetBearType): void {
  switch (netType) {
    case connection.NetBearType.BEARER_WIFI:
      // WiFi环境下可以预加载更多数据
      this.preloadMoreData();
      break;
    case connection.NetBearType.BEARER_CELLULAR:
      // 蜂窝网络下减少数据量
      this.reduceDataUsage();
      break;
  }
}

8. 错误处理与调试

8.1 常见错误处理

复制代码
private handleHttpError(error: BusinessError): void {
  switch (error.code) {
    case 401:
      console.error('权限不足,请重新登录');
      this.jumpToLogin();
      break;
    case 403:
      console.error('访问被拒绝');
      break;
    case 404:
      console.error('请求的资源不存在');
      break;
    case 408:
      console.error('请求超时,请检查网络连接');
      this.retryRequest();
      break;
    case 500:
      console.error('服务器内部错误');
      break;
    default:
      console.error('网络请求失败:', error.message);
  }
}

8.2 请求重试机制

复制代码
async function requestWithRetry(
  url: string, 
  options: object, 
  maxRetries: number = 3
): Promise<void> {
  let lastError: Error;
  
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const httpRequest = http.createHttp();
      const response = await httpRequest.request(url, options);
      
      if (response.responseCode === http.ResponseCode.OK) {
        return Promise.resolve(response);
      }
    } catch (err) {
      lastError = err;
      
      // 指数退避
      await new Promise(resolve => {
        setTimeout(resolve, Math.pow(2, attempt) * 1000);
      });
    }
  }
  
  return Promise.reject(lastError);
}

9. 实际应用场景示例

9.1 新闻列表获取

复制代码
class NewsService {
  async fetchNewsList(category: string, page: number = 1): Promise<News[]> {
    const httpRequest = http.createHttp();
    
    try {
      const response = await httpRequest.request(
        `https://api.news.com/news/${category}`,
        {
          method: http.RequestMethod.GET,
          extraData: {
            page: page,
            pageSize: 20
          }
        }
      );
      
      if (response.responseCode === http.ResponseCode.OK) {
        return JSON.parse(response.result.toString()).data as News[];
      } else {
        throw new Error(`HTTP错误: ${response.responseCode}`);
      }
    } finally {
      httpRequest.destroy();
    }
  }
}

9.2 用户登录实现

复制代码
async function userLogin(username: string, password: string): Promise<LoginResult> {
  const httpRequest = http.createHttp();
  
  try {
    const response = await httpRequest.request(
      'https://api.example.com/auth/login',
      {
        method: http.RequestMethod.POST,
        extraData: JSON.stringify({
          username: username,
          password: password
        }),
        header: {
          'Content-Type': 'application/json'
        }
      }
    );
    
    const result = JSON.parse(response.result.toString());
    
    if (response.responseCode === http.ResponseCode.OK && result.success) {
      // 保存登录状态
      await this.saveAuthToken(result.token);
      return { success: true, user: result.user };
    } else {
      return { 
        success: false, 
        error: result.message || '登录失败' 
      };
    }
  } catch (err) {
    return { 
      success: false, 
      error: err.message 
    };
  } finally {
    httpRequest.destroy();
  }
}

10. 总结

鸿蒙系统的HTTP网络请求框架提供了完整而强大的解决方案,从基础的请求发起到高级的安全配置,覆盖了各种应用场景的需求。关键要点包括:

  • 权限配置是基础:确保正确配置网络权限和明文传输设置

  • 资源管理很重要:及时销毁请求对象,避免内存泄漏

  • 错误处理要全面:考虑各种网络异常情况

  • 性能优化不可少:合理使用缓存、连接复用等策略

  • 异步编程是核心:熟练使用Promise和async/await

通过掌握这些知识,你能够构建出稳定、高效且用户体验良好的鸿蒙应用。在实际开发中,建议根据具体业务需求选择合适的配置和优化策略,并充分利用鸿蒙系统提供的网络状态管理能力,打造真正智能的分布式应用体验。

相关推荐
赵财猫._.1 小时前
HarmonyOS内存优化实战:泄漏检测、大对象管理与垃圾回收策略
华为·wpf·harmonyos
v***44671 小时前
PLC(电力载波通信)网络机制介绍
开发语言·网络·php
世界尽头与你1 小时前
CVE-2014-3566: OpenSSL 加密问题漏洞
网络·安全·网络安全·渗透测试
L***B5681 小时前
SQL 注入漏洞原理以及修复方法
网络·数据库·sql
ZeroNews内网穿透1 小时前
ZeroNews IP 访问控制能力
服务器·网络·网络协议·tcp/ip·安全·web安全·小程序
风浅月明1 小时前
[Harmony]跳转应用商店进行版本更新
harmonyos·版本更新
欧学明1 小时前
希影RS80 Ultra 鸿蒙巨幕 4K投影仪:2㎡阳台的多元光影体验
harmonyos·希影 rs80 ultra
马剑威(威哥爱编程)1 小时前
【鸿蒙开发实战篇】鸿蒙跨设备的碰一碰文件分享
华为·harmonyos
赵财猫._.1 小时前
鸿蒙超级终端体验:无缝流转的底层实现与用户体验优化
wpf·harmonyos·ux