联系我们
简单又实用的WordPress网站制作教学
当前位置:网站首页 > 程序开发学习 > 正文

HarmonyOS 窥探网络请求

作者:访客发布时间:2023-12-26分类:程序开发学习浏览:97


导读:介绍HarmonyOS平台中使用网络请求,需要引入"@ohos.net.http",并且需要在module.json5文件中申请网络权限,即“ohos.permis...

介绍

HarmonyOS 平台中使用网络请求,需要引入 "@ohos.net.http", 并且需要在 module.json5 文件中申请网络权限, 即 “ohos.permission.INTERNET”

本篇文章将尝试使用 @ohos.net.http 来实现网络请求

场景设定

  1. 网络请求主页面,包含两部分:a. 实验内容 b. 网络请求加载动画
  2. 简单封装网络请求,包含三部分:a. 异步 b. 同步 c. 自定义装饰器传参

场景主页面

  1. WeiBo UniDemo HuaWei : 请求顺序
  2. WeiBo1 UniDemo2 HuaWei3 : 异步/同步请求时,序号表示请求回来的顺序
  3. “开始网络请求-异步” : 开始异步请求
  4. “开始网络请求-同步” : 开始同步请求
  5. “开始网络请求-自定义方法装饰器” : 采用自定义方法装饰器进行传参,进而完成网络请求

初始状态.png

官方网络请求案例

注意:
每次请求都必须新创建一个HTTP请求实例,即只要发起请求,必须调用createHttp方法

官方指南

API手册

关于 @ohos.net.http 有三个request方法

  1. request(url: string, callback: AsyncCallback): void;
    1.1 如下“官方指南代码缩减版”使用到了这个方法

  2. request(url: string, options: HttpRequestOptions, callback: AsyncCallback): void;
    2.1 如下“官方指南代码” 使用了这个方法

  3. request(url: string, options?: HttpRequestOptions): Promise;
    3.1 将在后续实践代码中使用到

// 引入包名
import http from '@ohos.net.http';

// 每一个httpRequest对应一个HTTP请求任务,不可复用
let httpRequest = http.createHttp();
// 用于订阅HTTP响应头,此接口会比request请求先返回。可以根据业务需要订阅此消息
// 从API 8开始,使用on('headersReceive', Callback)替代on('headerReceive', AsyncCallback)。 8+
httpRequest.on('headersReceive', (header) => {
    console.info('header: ' + JSON.stringify(header));
});
httpRequest.request(
    // 填写HTTP请求的URL地址,可以带参数也可以不带参数。URL地址需要开发者自定义。请求的参数可以在extraData中指定
    "EXAMPLE_URL",
    {
        method: http.RequestMethod.POST, // 可选,默认为http.RequestMethod.GET
        // 开发者根据自身业务需要添加header字段
        header: {
            'Content-Type': 'application/json'
        },
        // 当使用POST请求时此字段用于传递内容
        extraData: {
            "data": "data to send",
        },
        expectDataType: http.HttpDataType.STRING, // 可选,指定返回数据的类型
        usingCache: true, // 可选,默认为true
        priority: 1, // 可选,默认为1
        connectTimeout: 60000, // 可选,默认为60000ms
        readTimeout: 60000, // 可选,默认为60000ms
        usingProtocol: http.HttpProtocol.HTTP1_1, // 可选,协议类型默认值由系统自动指定
    }, (err, data) => {
        if (!err) {
            // data.result为HTTP响应内容,可根据业务需要进行解析
            console.info('Result:' + JSON.stringify(data.result));
            console.info('code:' + JSON.stringify(data.responseCode));
            // data.header为HTTP响应头,可根据业务需要进行解析
            console.info('header:' + JSON.stringify(data.header));
            console.info('cookies:' + JSON.stringify(data.cookies)); // 8+
        } else {
            console.info('error:' + JSON.stringify(err));
            // 取消订阅HTTP响应头事件
            httpRequest.off('headersReceive');
            // 当该请求使用完毕时,调用destroy方法主动销毁
            httpRequest.destroy();
        }
    }
);
// 引入包名
import http from '@ohos.net.http';

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

httpRequest.request(
    // 填写HTTP请求的URL地址,可以带参数也可以不带参数。URL地址需要开发者自定义。请求的参数可以在extraData中指定
    "EXAMPLE_URL",
    (err, data) => {
        if (!err) {
            // data.result为HTTP响应内容,可根据业务需要进行解析
            console.info('Result:' + JSON.stringify(data.result));
            console.info('code:' + JSON.stringify(data.responseCode));
            // data.header为HTTP响应头,可根据业务需要进行解析
            console.info('header:' + JSON.stringify(data.header));
            console.info('cookies:' + JSON.stringify(data.cookies)); // 8+
        } else {
            console.info('error:' + JSON.stringify(err));
            // 取消订阅HTTP响应头事件
            httpRequest.off('headersReceive');
            // 当该请求使用完毕时,调用destroy方法主动销毁
            httpRequest.destroy();
        }
    }
);

场景布局

初始状态.png

基础页面组件代码

考虑到实际的场景会用到网络请求加载,因此这里将发挥 @BuilderParam 装饰器作用,先定义基础页面

组件中定义了 @Prop netLoad:boolean 变量来控制是否展示加载动画

@Component
export struct BasePage {
  @Prop netLoad: boolean

  //指向一个组件  
  @BuilderParam aB0: () => {}

  build(){
     Stack(){
       
       //为组件占位
       this.aB0()

       if (this.netLoad) {
         LoadingProgress()
           .width(px2vp(150))
           .height(px2vp(150))
           .color(Color.Blue)
       }

     }.hitTestBehavior(HitTestMode.None)
  }

}

主页面布局代码

import { BasePage } from './BasePage'

@Entry
@Component
struct NetIndex {
  @State netLoad: number = 0
  @State msg: string = ''

  build() {
      Stack(){
        BasePage({netLoad: this.netLoad != 0}) {
          Column( {space: 20} ){

            Row({space: 20}){
              Text('WeiBo').fontColor(Color.Black)
              Text('UniDemo').fontColor(Color.Black)
              Text('HuaWei').fontColor(Color.Black)
            }

            Row({space: 20}){
              Text('WeiBo' + this.weiboIndex)
              Text('UniDemo' + this.uniIndex)
              Text('HuaWei' + this.huaweiIndex)
            }

            Button('开始网络请求 - 异步').fontSize(20).onClick( () => {
                ...
            })

            Button('开始网络请求 - 同步').fontSize(20).onClick( () => {
                ...
            })

            Button('开始网络请求-自定义方法装饰器').fontSize(20).onClick( () => {
              ...
            })

            Scroll() {
              Text(this.msg).width('100%')
            }
            .scrollable(ScrollDirection.Vertical)
          }
          .width('100%')
          .height('100%')
          .padding({top: px2vp(120)})
        }

      }
  }

}

简单装封装网络请求

函数传参,直接调用封装方法

网络请求样例
WeiBo为数据结构体,暂时不用关心,后续会贴出完整代码,这里仅仅是演示网络请求用法

//引用封装好的HNet网络工具类
import HNet from './util/HNet'

@State msg: string = ''
    
getWeiBoData(){
   HNet.get<WeiBo>({
  url: 'https://m.weibo.cn/api/feed/trendtop?containerid=102803_ctg1_4188_-_ctg1_4188',
}).then( (r) => {

  this.msg = ''

  if(r.code == 0 && r.result){
    r.result.data.statuses.forEach((value: WeiBoItem) => {
      this.msg = this.msg.concat(value.created_at + ' ' + value.id + '\n')
    })
  } else {
    this.msg = r.code + ' ' + r.msg
  }
  console.log('顺序-weibo-' + (new Date().getTime() - starTime))

  this.netLoad--

})    
   
}

自定义方法装饰器,完成传参调用

网络请求样例

NetController.getWeiBo<WeiBo>().then( r => {
   ......
})    

按照业务定义传参

import { Get, NetResponse } from './util/HNet'

export default class BizNetController {

  @Get('https://m.weibo.cn/api/feed/trendtop?containerid=102803_ctg1_4188_-_ctg1_4188')
  static getWeiBo<WeiBo>(): Promise<NetResponse<WeiBo>>{ return }

}

封装的网络请求代码

import http from '@ohos.net.http';

//自定义网络请求参数对象    
class NetParams{
  url: string
  extraData?: JSON
}

//自定义数据公共结构体    
export class NetResponse<T> {
  result: T
  code: number
  msg: string
}

//网络封装工具类    
class HNet {

  //POST 请求方法  
  static post<T>(options: NetParams): Promise<NetResponse<T>>{
    return this.request(options, http.RequestMethod.POST)
  }

  //GET 请求方法  
  static get<T>(options: NetParams): Promise<NetResponse<T>>{
    return this.request(options, http.RequestMethod.GET)
  }

    
  private static request<T>(options: NetParams, method: http.RequestMethod): Promise<NetResponse<T>>{

    let r = http.createHttp()

    return r.request(options.url, {
      method: method,
      extraData: options.extraData != null ? JSON.stringify(options.extraData) : null
    }).then( (response: http.HttpResponse) => {

      let netResponse = new NetResponse<T>()

      let dataType = typeof response.result

      if(dataType === 'string'){
         console.log('结果为字符串类型')
      }

      if(response.responseCode == 200){
        netResponse.code = 0
        netResponse.msg = 'success'
        netResponse.result = JSON.parse(response.result as string)

      } else {
        //出错
        netResponse.code = -1
        netResponse.msg = 'error'

      }

      return netResponse

    }).catch( reject => {
      console.log('结果发生错误')

      let netResponse = new NetResponse<T>()
      netResponse.code = reject.code
      netResponse.msg  = reject.message
      return netResponse

    }).finally( () => {
       //网络请求完成后,需要进行销毁
       r.destroy()
    })

  }

}

export default HNet 
    
//用于装饰器传参
export function Get(targetUrl: string) : MethodDecorator {

  return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
        //替换方法
        descriptor.value = () => {
           let options = new NetParams()
           options.url = targetUrl
            return HNet.get(options)
        }
  }

}
    

完整代码

代码结构

net/BasePage.ets
net/NetRequest.ets
net/util/HNet.ts
net/viewmodel/WeiBoModel.ts
net/BizNetController.ets

详细代码

@Component
export struct BasePage {
  @Prop netLoad: boolean

  @BuilderParam aB0: () => {}

  build(){
     Stack(){

       this.aB0()

       if (this.netLoad) {
         LoadingProgress()
           .width(px2vp(150))
           .height(px2vp(150))
           .color(Color.Blue)
       }

     }.hitTestBehavior(HitTestMode.None)
  }

}   
import HNet from './util/HNet'
import NetController from './BizNetController'
import { WeiBo, WeiBoItem } from './viewmodel/WeiBoModel'
import { BasePage } from './BasePage'

@Entry
@Component
struct NetIndex {
  @State netLoad: number = 0
  @State msg: string = ''

  @State weiboColor: Color = Color.Black
  @State uniColor: Color = Color.Black
  @State huaweiColor: Color = Color.Black

  @State weiboIndex: number = 1
  @State uniIndex: number = 2
  @State huaweiIndex: number = 3

  private  TEST_Target_URL: string[] = [
    'https://m.weibo.cn/api/feed/trendtop?containerid=102803_ctg1_4188_-_ctg1_4188',
    'https://unidemo.dcloud.net.cn/api/news',
    'https://developer.huawei.com/config/cn/head.json',
  ]

  build() {
      Stack(){
        BasePage({netLoad: this.netLoad != 0}) {
          Column( {space: 20} ){

            Row({space: 20}){
              Text('WeiBo').fontColor(Color.Black)
              Text('UniDemo').fontColor(Color.Black)
              Text('HuaWei').fontColor(Color.Black)
            }

            Row({space: 20}){
              Text('WeiBo' + this.weiboIndex).fontColor(this.weiboColor)
              Text('UniDemo' + this.uniIndex).fontColor(this.uniColor)
              Text('HuaWei' + this.huaweiIndex).fontColor(this.huaweiColor)
            }

            Button('开始网络请求 - 异步').fontSize(20).onClick( () => {
                this.weiboColor = Color.Black
                this.uniColor = Color.Black
                this.huaweiColor = Color.Black
                this.weiboIndex = 1
                this.uniIndex = 2
                this.huaweiIndex = 3
                this.asyncGetData()
            })

            Button('开始网络请求 - 同步').fontSize(20).onClick( () => {
                this.weiboColor = Color.Black
                this.uniColor = Color.Black
                this.huaweiColor = Color.Black

                this.weiboIndex = 1
                this.uniIndex = 2
                this.huaweiIndex = 3
                this.syncGetData()
            })

            Button('开始网络请求-自定义方法装饰器').fontSize(20).onClick( () => {
              this.getWeiBoListByController()
            })

            Scroll() {
              Text(this.msg).width('100%')
            }
            .scrollable(ScrollDirection.Vertical)
          }
          .width('100%')
          .height('100%')
          .padding({top: px2vp(120)})
        }

      }
  }

  asyncGetData(){

    this.netLoad = 3;

    this.TEST_Target_URL.forEach( (value) => {

      HNet.get({
        url: value,
      }).then( (r) => {

        this.msg = JSON.stringify(r)

        if(value.indexOf('weibo') != -1){
          this.weiboColor = Color.Green
          this.weiboIndex = 3 - this.netLoad + 1
        } else if(value.indexOf('unidemo') != -1){
          this.uniColor = Color.Green
          this.uniIndex = 3 - this.netLoad + 1
        } else if(value.indexOf('huawei') != -1){
          this.huaweiColor = Color.Green
          this.huaweiIndex = 3 - this.netLoad + 1
        }

        this.netLoad--

      })
    })

  }

  async syncGetData() {

    let starTime
    let url
    this.netLoad = 3;

    starTime = new Date().getTime()
    url = this.TEST_Target_URL[0]

    starTime = new Date().getTime()
    if(url.indexOf('weibo') != -1){
      console.log('顺序-请求-weibo')
    } else if(url.indexOf('unidemo') != -1){
      console.log('顺序-请求-unidemo')
    } else if(url.indexOf('huawei') != -1){
      console.log('顺序-请求-huawei')
    }

    await HNet.get<WeiBo>({
      url: url,
    }).then( (r) => {

      this.msg = ''

      if(r.code == 0 && r.result){
        r.result.data.statuses.forEach((value: WeiBoItem) => {
          this.msg = this.msg.concat(value.created_at + ' ' + value.id + '\n')
        })
      } else {
        this.msg = r.code + ' ' + r.msg
      }

      if(url.indexOf('weibo') != -1){
        this.weiboColor = Color.Green
        this.weiboIndex = 3 - this.netLoad + 1
        console.log('顺序-返回-weibo-' + (new Date().getTime() - starTime))
      } else if(url.indexOf('unidemo') != -1){
        this.uniColor = Color.Green
        this.uniIndex = 3 - this.netLoad + 1
        console.log('顺序-返回-unidemo-' + (new Date().getTime() - starTime))
      } else if(url.indexOf('huawei') != -1){
        this.huaweiColor = Color.Green
        this.huaweiIndex = 3 - this.netLoad + 1
        console.log('顺序-返回-huawei-' + (new Date().getTime() - starTime))
      }

      this.netLoad--

    })

    starTime = new Date().getTime()
    url = this.TEST_Target_URL[1]

    starTime = new Date().getTime()
    if(url.indexOf('weibo') != -1){
      console.log('顺序-请求-weibo')
    } else if(url.indexOf('unidemo') != -1){
      console.log('顺序-请求-unidemo')
    } else if(url.indexOf('huawei') != -1){
      console.log('顺序-请求-huawei')
    }

    await HNet.get({
      url: url,
    }).then( (r) => {

      this.msg = JSON.stringify(r)

      if(url.indexOf('weibo') != -1){
        this.weiboColor = Color.Green
        this.weiboIndex = 3 - this.netLoad + 1
        console.log('顺序-返回-weibo-' + (new Date().getTime() - starTime))
      } else if(url.indexOf('unidemo') != -1){
        this.uniColor = Color.Green
        this.uniIndex = 3 - this.netLoad + 1
        console.log('顺序-返回-unidemo-' + (new Date().getTime() - starTime))
      } else if(url.indexOf('huawei') != -1){
        this.huaweiColor = Color.Green
        this.huaweiIndex = 3 - this.netLoad + 1
        console.log('顺序-返回-huawei-' + (new Date().getTime() - starTime))
      }

      this.netLoad--

    })

    starTime = new Date().getTime()
    url = this.TEST_Target_URL[2]

    starTime = new Date().getTime()
    if(url.indexOf('weibo') != -1){
      console.log('顺序-请求-weibo')
    } else if(url.indexOf('unidemo') != -1){
      console.log('顺序-请求-unidemo')
    } else if(url.indexOf('huawei') != -1){
      console.log('顺序-请求-huawei')
    }

    await HNet.get({
      url: url,
    }).then( (r) => {

      this.msg = JSON.stringify(r)

      if(url.indexOf('weibo') != -1){
        this.weiboColor = Color.Green
        this.weiboIndex = 3 - this.netLoad + 1
        console.log('顺序-返回-weibo-' + (new Date().getTime() - starTime))
      } else if(url.indexOf('unidemo') != -1){
        this.uniColor = Color.Green
        this.uniIndex = 3 - this.netLoad + 1
        console.log('顺序-返回-unidemo-' + (new Date().getTime() - starTime))
      } else if(url.indexOf('huawei') != -1){
        this.huaweiColor = Color.Green
        this.huaweiIndex = 3 - this.netLoad + 1
        console.log('顺序-返回-huawei-' + (new Date().getTime() - starTime))
      }

      this.netLoad--

    })

  }

  getHuaWeiSomeDataByNet(){

    this.netLoad = 1

    let starTime = new Date().getTime()

    console.log('顺序-huawei-请求' + starTime)

    HNet.get({
      url: 'https://developer.huawei.com/config/cn/head.json',
    }).then( (r) => {

      this.msg = JSON.stringify(r, null, '\t')

      this.netLoad--

      console.log('顺序-huawei-' + (new Date().getTime() - starTime))

    })

  }

  getWeiBoListByHNet(){

    this.netLoad = 1

    let starTime = new Date().getTime()

    console.log('顺序-weibo-请求' + starTime)

    HNet.get<WeiBo>({
      url: 'https://m.weibo.cn/api/feed/trendtop?containerid=102803_ctg1_4188_-_ctg1_4188',
    }).then( (r) => {

      this.msg = ''

      if(r.code == 0 && r.result){
        r.result.data.statuses.forEach((value: WeiBoItem) => {
          this.msg = this.msg.concat(value.created_at + ' ' + value.id + '\n')
        })
      } else {
        this.msg = r.code + ' ' + r.msg
      }
      console.log('顺序-weibo-' + (new Date().getTime() - starTime))

      this.netLoad--

    })
  }

  getWeiBoListByController(){

    this.netLoad = 1

    NetController.getWeiBo<WeiBo>().then( r => {

      this.msg = ''

      if(r.code == 0 && r.result){
        r.result.data.statuses.forEach((value: WeiBoItem) => {
          this.msg = this.msg.concat(value.created_at + ' ' + value.id + '\n' + value.source + '\n')
        })
      } else {
        this.msg = r.code + ' ' + r.msg
      }

      this.netLoad--

    })
  }

}    
import { Get, NetResponse } from './util/HNet'

export default class BizNetController {

  @Get('https://m.weibo.cn/api/feed/trendtop?containerid=102803_ctg1_4188_-_ctg1_4188')
  static getWeiBo<WeiBo>(): Promise<NetResponse<WeiBo>>{ return }

}    
import http from '@ohos.net.http';

class NetParams{
  url: string
  extraData?: JSON
}

export class NetResponse<T> {
  result: T
  code: number
  msg: string
}

class HNet {

  static post<T>(options: NetParams): Promise<NetResponse<T>>{
    return this.request(options, http.RequestMethod.POST)
  }

  static get<T>(options: NetParams): Promise<NetResponse<T>>{
    return this.request(options, http.RequestMethod.GET)
  }

  private static request<T>(options: NetParams, method: http.RequestMethod): Promise<NetResponse<T>>{

    let r = http.createHttp()

    return r.request(options.url, {
      method: method,
      extraData: options.extraData != null ? JSON.stringify(options.extraData) : null
    }).then( (response: http.HttpResponse) => {

      let netResponse = new NetResponse<T>()

      let dataType = typeof response.result

      if(dataType === 'string'){
         console.log('结果为字符串类型')
      }

      if(response.responseCode == 200){
        netResponse.code = 0
        netResponse.msg = 'success'
        netResponse.result = JSON.parse(response.result as string)

      } else {
        //出错
        netResponse.code = -1
        netResponse.msg = 'error'

      }

      return netResponse

    }).catch( reject => {
      console.log('结果发生错误')

      let netResponse = new NetResponse<T>()
      netResponse.code = reject.code
      netResponse.msg  = reject.message
      return netResponse

    }).finally( () => {
       r.destroy()
    })

  }

}

export default HNet

export function Get(targetUrl: string) : MethodDecorator {

  return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
        //替换方法
        descriptor.value = () => {
           let options = new NetParams()
           options.url = targetUrl
            return HNet.get(options)
        }
  }

}
    

export class WeiBo{
  ok: number
  http_code: number
  data: WeiBoDataObj
}

export class WeiBoDataObj{
  total_number: number
  interval: number
  remind_text: string
  page: number
  statuses: Array<WeiBoItem>
}

export class WeiBoItem{
  created_at: string
  id: string
  source: string
  textLength: number
}
    

标签:网络HarmonyOS


程序开发学习排行
最近发表
网站分类
标签列表