封装网络请求 鸿蒙APP HarmonyOS ArkTS

一、效果展示

通过在页面直接调用 userLogin(params) 方法,获取登录令牌

二、申请网络权限

访问网络时候首先需要申请网络权限,需要修改 src/main 目录下的 module.json5 文件,加入 requestPermissions 属性,详见官方文档

【声明权限】https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/declare-permissions-V5

复制代码
{
  "module": {
    // ...
    "requestPermissions":[
      {
        "name" : "ohos.permission.INTERNET",
        "usedScene": {
          "abilities": [
            "FormAbility"
          ],
          "when":"inuse"
        }
      },
      {
        "name" : "ohos.permission.GET_NETWORK_INFO",
        "usedScene": {
          "abilities": [
            "FormAbility"
          ],
          "when":"inuse"
        }
      }
    ]
  }
}

三、实现代码

共分为 7 个步骤,其中第 1、2、3、5 步都是创建基础实体,第 4 步为请求工具封装、第 6 步为API封装、第 7 步为页面调用测试,我会在最后贴上文件目录结构

1、创建常量类 CommonConstant.ets

在这个常量类中主要定义后端服务IP端口,以及一些需要使用的状态码信息

复制代码
/**
 * HTTP API
 */
export class Domain {

  // 后端服务IP
  static readonly SERVER: string = 'http://localhost:8999'

}

/**
 * HTTP状态类
 */
export class HttpStatus {

  // 成功
  static readonly SUCCESS: number = 200

  // 失败
  static readonly ERROR: number = 500

}

export const enum ContentType {

  // 响应体类型
  JSON = 'application/json'
  
}

2、创建请求实体类 RequestBody.ets

这个请求实体类主要可以实现简单的传输【请求地址、请求方式、请求参数】这三个参数,再经过封装的工具去发送网络请求

复制代码
export class RequestBody {

  url: string;

  method: string;

  data: Object;

  constructor() {
    this.url = ''
    this.method = 'GET'
    this.data = new Object
  }
}

3、创建响应实体类 ResponseResult.ets

这个响应实体主要对应后台的返回参数,比如我这里定义的后台响应码为【code】,信息为【msg】,响应数据为【data】,这个可以自行修改

复制代码
export class ResponseResult {

  code: number;

  msg: string | Resource;

  data: ArrayBuffer | Object | string

  constructor() {
    this.code = 0;
    this.msg = '';
    this.data = '';
  }
}

4、创建请求工具类 HttpRequest.ets

详见官方文档

【HTTP数据请求】https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/http-\> request-V5

【异步并发概述 (Promise和async/await)】https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/async-concurrency-overview-V5#promise

复制代码
// 这里需要引入第 2 步和第 3 步创建的请求和响应实体
import { ResponseResult } from '../response/ResponseResult'
import { RequestBody } from '../response/RequestBody'

// 这里需要引入第 1 步公共常量类
import { Domain, HttpStatus, ContentType } from '../constant/CommonConstant'

// 这里引用 HTTP 库
import http from '@ohos.net.http'

// HTTP响应处理时候需要的库
import { BusinessError } from '@kit.BasicServicesKit';

class HttpRequest {
  request(requestBody: RequestBody) {
    const promise: Promise<ResponseResult> = new Promise((resolve: Function, reject: Function) => {

      console.log('创建HTTP请求,请求地址:' + Domain.SERVER + requestBody.url + ',请求方式:' + requestBody.method + ',请求体:' + JSON.stringify(requestBody.data))

      // 创建HTTP请求
      const httpRequest = http.createHttp()

	  // 在这里发送 HTTP 请求,并且需要设置Url、Header、Body等信息
      httpRequest.request(
        Domain.SERVER + requestBody.url,
        {
          method: isPost(requestBody.method) ? http.RequestMethod.POST : http.RequestMethod.GET,
          readTimeout: 10000,
          header: {
            'Content-Type': ContentType.JSON
          },
          connectTimeout: 10000,
          extraData: requestBody.data
        },
        (err: BusinessError, data: http.HttpResponse) => {
          // 回调之后判断是否提示 Error
          if (!err) {

            let result = `${data.result}`
            let resultJSON: ResponseResult = JSON.parse(result)

	        // 判断响应码是否成功
            if (data.responseCode === HttpStatus.SUCCESS) {

              if (resultJSON.code === 0) {
                console.info('请求成功:' + resultJSON.data)

                resolve(resultJSON)
              } else {
                reject(new Error('' + resultJSON.msg))
                errorDialog('' + resultJSON.msg)
              }
            } else {
              reject(new Error('' + resultJSON.msg))
              errorDialog('' + resultJSON.msg)
            }

            // 当该请求使用完毕时,调用destroy方法主动销毁
            httpRequest.destroy();
          } else {
            console.error('ERROR:' + JSON.stringify(err));

            if (err.code === 2300007) {
              errorDialog('无法连接至服务器,请稍后重试')
            }

            if (err.code === 2300028) {
              errorDialog('当前网络环境不稳定,请稍后重试')
            }

            // 当该请求使用完毕时,调用destroy方法主动销毁
            httpRequest.destroy();

            reject(new Error('当前网络环境不稳定,请稍后重试'))
          }
        }
      )
    })

    return promise;
  }
}

const httpRequest = new HttpRequest();
export default httpRequest as HttpRequest;

// 判断是否是GET方法
function isGet(method: string): boolean | undefined {

  if (method === http.RequestMethod.GET) {
    return true;
  }

  return false;
}

// 判断是否是POST方法
function isPost(method: string): boolean | undefined {

  if (method === http.RequestMethod.POST) {
    return true;
  }

  return false;
}

// 提示错误
function errorDialog(msg: string) {
  console.error(msg)
}

5、创建一个用户登录实体 userInfo.ets

这个用户实体类包含用户的账号和密码信息,是登录所需

复制代码
export class UserInfo {

  account: string;

  password: string;

  constructor() {
    this.account = ''
    this.password = ''
  }
}

6、创建一个用户API user.ets

这个API的作用就是统一格式,统一使用【url】、【data】、【method】这三个进行网络请求,也是在请求工具类 HttpRequest.ets 基础上的二次封装

复制代码
// 这里引入第 4 步创建的请求工具类
import HttpRequest from '../request/HttpRequest'

// 这里引入第 3 步创建的响应体
import { ResponseResult } from '../response/ResponseResult'

// 这里引入第 5 步创建的自定义用户对象,主要用于定义各参数的类型
import { UserInfo } from '../../entity/userInfo'

// 用户登录 API
export function userLogin(params: UserInfo): Promise<ResponseResult> {
  return HttpRequest.request({
    url: '/auth/login',
    data: params,
    method:'POST'
  })
}

7、在页面尝试调用 index.ets

最后在我们的页面启动时直接调用 user.ets 中的 userLogin 方法进行登录测试

复制代码
// 这里需要引入第 6 步创建的用户API
import { userLogin } from '../common/api/user';

@Entry
@Component
struct Index {

  // 在进入页面时调用 userLogin 接口进行测试
  aboutToAppear(): void {
    userLogin({account: 'admin', password: 'Admin@2024'}).then(res => {
      console.info('页面成功获取到用户信息:' + res.data)
    })
  }

  build() {
    RelativeContainer() {
      
    }
  }
}

四、目录结构

总共 7 个步骤创建了 7 个文件,希望对您有所帮助

相关推荐
有毒的教程21 分钟前
Ubuntu 网络代理设置教程
linux·网络·ubuntu
黄昏回响28 分钟前
计算机系统基础知识(九):软件篇之网络协议详解
网络·网络协议·面试·改行学it
桌面运维家37 分钟前
KVM虚拟机:Neutron网络故障诊断与修复实战
服务器·网络·php
F1FJJ1 小时前
Shield CLI 的 PostgreSQL 插件 v0.5.0 发布:数据库导出 + 协作增强,ER 图全新体验
网络·数据库·docker·postgresql·go
lxysbly1 小时前
鸿蒙harmonyos端怀旧游戏模拟器,支持fc红白机 街机 gba psp ps1 nds n64世嘉md gbc gb sfc等主机
游戏·华为·harmonyos
天启HTTP1 小时前
多线程环境下,动态IP怎么分配最合理
java·服务器·网络
serve the people2 小时前
ACME 协议流程与AllinSSL 的关系(三)
服务器·网络·https
网管NO.12 小时前
OpenClaw 多模型配置完整教程(WSL2 + Ubuntu)
运维·网络·人工智能·ubuntu
昵称只能一个月修改一次。。。2 小时前
ARM基本知识
网络
坚定的共产主义生产设备永不宕机2 小时前
OSPF实操配置
网络·智能路由器