鸿蒙学习笔记(5)-HTTP请求数据

发布于:2025-04-17 ⋅ 阅读:(27) ⋅ 点赞:(0)

一、Http请求数据

http模块是鸿蒙内置的一个模块,提供了网络请求的能力。不需要再写比较原始的AJAS代码。

ps:在项目中如果要访问网络资源,不管是图片文件还是网络请求,必须给项目开放权限。

(1)网络连接方式

HTTP数据请求连接:通过HTTP发起的一个单向数据请求。

WebSocket连接:使用WebSocket建立服务器与客户端的双向连接。

Socket连接:通过Socket进行数据传输,更加底层。

(2)涉及接口文档

类型 说明

http.createHttp()

创建一个HTTP请求,里面包括发起请求、中断请求、订阅/取消订阅HTTP Response Header事件。

HttpRequest()

根据URL地址,发起HTTP网络请求。

requestInStream()

根据URL地址,发起HTTP网络请求并返回流式响应,得到二进制数据,应用到文件下载,从后端拿到的不再是JSON和字符串,而是二进制数据。
destroy() 中断请求任务。

(3)request接口开发步骤 

1、步骤概述

1、从@kit.NetworkKit中导入http命名空间。Kit是我们项目需要用到的各种服务,如网络服务,分布式管理服务,蓝牙通信等。

2、调用creatHttp()方法,创建一个HttpRequest对象。

3、调用该对象的request()方法,订阅http响应头事件,此接口会比request请求先返回。可以根据业务需要订阅此消息。(此步骤不是必须,是用来监控响应头信息,如果你想发请求给后端,想要先知道后端返回的数据是JSON还是文件之类的,可以用此监控,他会比内容先返回客户端。)

4、调用该对象的equest()方法,传入http请求的url地址和可选参数,发起网络请求。

5、得到结果过后,按照实际业务需要,解析返回结果,筛选或者进行数据转化。

6、调用该对象的off()方法,取消订阅http响应头事件。

7、当请求使用完毕时,调用destroy()方法主动销毁。

2、封装代码:

//在common模块中封装一个基础的请求工具

import { http } from "@kit.NetworkKit";

//封装请求代码,考虑到以后每个模块都要发送请求,默认放在common模块中。
//1、导入
export function MyRequest(
  url:string,
  method:http.RequestMethod,
  requestData:string){
  //2、创建http请求
  const httpRequest = http.createHttp()

  //3、可以用httprequest监听响应头(不是必须)
  httpRequest.on('headersReceive', (header: Object) => {
    console.info('header: ' + JSON.stringify(header));
  });

  httpRequest.request(url, {
    method:method,//请求方式
    header:{//设置请求头
      //前端浏览器告诉后端,前端传递的数据格式
      'Content-Type': 'application/json'
    },
    extraData:requestData, //设置请求要传给后端的数据
    connectTimeout:9000,  //前端发送数据给后端如果9秒没有结果,前端主动终止行为
    readTimeout:9000, //读取数据超过9秒,告诉前端请求失败
  },(error:Error,data:http.HttpResponse)=>{
    //error没有内容代表成功
    if (!error) {
      console.log(`请求成功,返回数据:${JSON.stringify(data)}`)
      // 取消订阅HTTP响应头事件。
      httpRequest.off('headersReceive');
      // 当该请求使用完毕时,开发者务必调用destroy方法主动销毁该JavaScript Object。
      httpRequest.destroy();
    }else {
     console.log(`请求失败,具体原因:${JSON.stringify(error)}`)
      // 取消订阅HTTP响应头事件。
      httpRequest.off('headersReceive');
      // 当该请求使用完毕时,开发者务必调用destroy方法主动销毁该JavaScript Object。
      httpRequest.destroy();
    }
  })
}

 3、使用说明:

在页面中要使用这个工具来测试请求是否成功,在common/index.ets文件中先暴露。

export  {MyRequest} from './src/main/ets/utils/HttpUtils'

在home页面或者组件中,引入对应的函数

import {MyRequest} from '@ohos/common'


///比如跟事件绑定,测试数据是否能收到
.onClick((event:ClickEvent) => {
          MyRequest(
            'http://47.98.128.191:4001/home/swiperdate',
            http.RequestMethod.GET,
            ''
          )
        })

此时可以看到日志可以收到:

 此时请求发送完毕能够得到后端数据,但请求不是直接在页面或者组件中编写的代码,而是提取到了common模块中,如何拿到服务端的数据并显示到页面上,这才是需要解决的问题。

4、泛型编程

typescript中非常重要的一个概念:泛型编程

利用一个简单的案例:

function computed(params1:number,params2:number):number{
  return params1 +params2
}

computed(1,3)//编译通过
computed('xiao','ming')//编译失败,因为只接受number类型

为了简化上面的代码,使代码更加灵活,尤其是在数据约束上,既要增加约束,又要让参数支持更多类型,或者更加灵活,设计方式便是采用泛型的方式来设计参数类型 。

function computed<T>(params1:T,params2:T):T{
  return params1 +params2
}

computed<number>(1,3)   //编译通过
computed<string>('xiao','ming')   //编译通过
computed<bollean>(true,false)   //编译通过

同一个函数因为有了泛型,可以多次使用 ,这里我们以上面出现的问题:如何拿到服务端的数据并显示到页面上,利用promise来解决。通过promise对象将异步的请求代码封装到容器中获取到结果。

import { http } from "@kit.NetworkKit";
//BasicConstants下暴露基础URL地址,和传入的资源路径拼接
import { BasicConstants} from '../../constants/BasicConstants'
//封装请求代码,考虑到以后每个模块都要发送请求,默认放在common模块中。
//1、导入
export function MyRequest(
  url:string,
  method:http.RequestMethod,
  requestData:string){
  //2、创建http请求
  const httpRequest = http.createHttp()
  return new Promise((reslove:(value:string)=>void,reject:(value?:string)=>void)=>{
    //request发送请求就是异步代码
    httpRequest.request(
      //不再简单是url,而是做一下拼接基础地址
      BasicConstants.BASE_URL+url,
      {
      method:method,//请求方式
      header:{//设置请求头
        //前端浏览器告诉后端,前端传递的数据格式
        'Content-Type': 'application/json'
      },
      extraData:requestData, //设置请求要传给后端的数据
      connectTimeout:9000,  //前端发送数据给后端如果9秒没有结果,前端主动终止行为
      readTimeout:9000, //读取数据超过9秒,告诉前端请求失败
    },(error:Error,data:http.HttpResponse)=>{
      //error没有内容代表成功
      if (!error) {
        console.log(`请求成功,返回数据:${JSON.stringify(data,null,2)}`)
        reslove(JSON.stringify(data))
        // 取消订阅HTTP响应头事件。
        httpRequest.off('headersReceive');
        // 当该请求使用完毕时,开发者务必调用destroy方法主动销毁该JavaScript Object。
        httpRequest.destroy();
      }else {
        console.log(`请求失败,具体原因:${JSON.stringify(error)}`)
        reject(JSON.stringify(error))
        // 取消订阅HTTP响应头事件。
        httpRequest.off('headersReceive');
        // 当该请求使用完毕时,开发者务必调用destroy方法主动销毁该JavaScript Object。
        httpRequest.destroy();
      }
    })
  })

}

页面中获取请求返回的数据: 

 但此时传入参数是固定必须是string类型,不够灵活,接下来进一步封装,利用泛型编程做进一步优化使得代码实现复用。K代表请求的数据类型,T代表返回的数据类型

import { http } from "@kit.NetworkKit";
import { BasicConstants} from '../../constants/BasicConstants'
//封装请求代码,考虑到以后每个模块都要发送请求,默认放在common模块中。
//1、导入
//K代表请求的数据类型,T代表返回的数据类型
export function MyRequest<T,K>(
  url:string,
  method:http.RequestMethod,
  requestData?:K){
  //2、创建http请求
  const httpRequest = http.createHttp()
  return new Promise((reslove:(value:T)=>void,reject:(value?:string)=>void)=>{
    //request发送请求就是异步代码
    httpRequest.request(
      //不再简单是url,而是做一下拼接基础地址
      BasicConstants.BASE_URL+url,
      {
      method:method,//请求方式
      header:{//设置请求头
        //前端浏览器告诉后端,前端传递的数据格式
        'Content-Type': 'application/json'
      },
      extraData:JSON.stringify(requestData)||'', //设置请求要传给后端的数据
      connectTimeout:9000,  //前端发送数据给后端如果9秒没有结果,前端主动终止行为
      readTimeout:9000, //读取数据超过9秒,告诉前端请求失败
    },(error:Error,data:http.HttpResponse)=>{
      //error没有内容代表成功
      if (!error) {
        console.log(`请求成功,返回数据:${JSON.stringify(data,null,2)}`)
        //这里如何
        reslove(JSON.parse(data.result as string))
        // 取消订阅HTTP响应头事件。
        httpRequest.off('headersReceive');
        // 当该请求使用完毕时,开发者务必调用destroy方法主动销毁该JavaScript Object。
        httpRequest.destroy();
      }else {
        console.log(`请求失败,具体原因:${JSON.stringify(error)}`)
        reject(JSON.stringify(error))
        // 取消订阅HTTP响应头事件。
        httpRequest.off('headersReceive');
        // 当该请求使用完毕时,开发者务必调用destroy方法主动销毁该JavaScript Object。
        httpRequest.destroy();
      }
    })
  })

}

 页面中获取请求返回的数据: 

完整工具封装见资源文件。

(4)HTTP数据请求

4.1 导入HTTP模块

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


4.2 使用HTTP模块发送请求,处理响应.

4.2.1 创建一个http的请求对象,不可复用
const httpRequest = http.createHttp()
4.2.2 调用一个request方法,发起网络请求。

ps:像这种可能存在数据请求发送完但数据还没收到,因此此处方法执行完会存放一个未来会完成的结果Promise。

req.request('http://localhost:3000/users',//请求URL地址
{   
    //请求选项HttpRequestOptions
    metnod:http.RequestMethod.GET,
    extraData:{'param1':'value1'}    //k1=v1&k1=v2
}
)  
HttpRequestOptions 说明:
名称 类型 描述
method RequestMethod 请求方式,GET(查询)、POST(表单提交,新增)、PUT(修改)、DELETE(删除)等
extraData string|Object 请求参数
header Object 请求头字段
connectTimeout number 请求超时时间,单位毫秒,默认60000ms
readTimeout number 读取超时间,同上


4.2.3 获取服务器响应的内容,Promise提供两种方法分别是then成功回调和catch失败回调。
.then((resp:http.HttpResponse)=>{
    if(resp.responseCode === 200){
       //请求成功
    }
 })
.catch((err:Error)=>{
    //请求失败
});
HttpResponse 说明: 
名称 类型 描述
responseCode responseCode 响应状态码
header Object 响应头
cookies string 响应返回的cookies
result string|Object 响应体,默认是JSON字符串
resultType HttpDataType 返回值类型

二、Promise

Promise是es6提出的一个概念,主要用来解决异步回调的问题。Promise是一个数据容器,保存了未来的一个结果,Promise本身是可以用来存放同步代码和异步代码,平时经常用来解决存放异步代码。以下是网络请求的一个发展历程:

发送网络请求,获取结果

1.1 发送网络请求

//"AJAX"(Asynchronous JavaScript and XML,异步 JavaScript 和 XML)
//浏览器默认提供的对象,获取结果
const xmlhttp = new XMLhttpRequest()
//连接服务器
xmlhttp.open('GET','http://+地址',true)
xmlhttp.send('id=1')

//监听状态码,当状态码是200时
xmlhttp.onreadystatechange = function(){
  //首先状态码必须是200,readyState代表xmlhttp加载过程
  if(xmlhttp.status == 200 && xmlhttp.readyState == 4){
     const result = xmlhttp.responseText
     //拿到数据后转化
        const obj = JSON.parse(result)
     }
}

1.2 将其封装工具

function ajas( {method='GET',url,data='',async=true} ){
  //"AJAX"(Asynchronous JavaScript and XML,异步 JavaScript 和 XML)
  //浏览器默认提供的对象,获取结果
  const xmlhttp = new XMLhttpRequest()
  //连接服务器
  xmlhttp.open(method,url,async)
  xmlhttp.send(data)

  //监听状态码,当状态码是200时
  xmlhttp.onreadystatechange = function(){
    //首先状态码必须是200,readyState代表xmlhttp加载过程
    if(xmlhttp.status == 200 && xmlhttp.readyState == 4){
       const result = xmlhttp.responseText
       //拿到数据后转化
          const obj = JSON.parse(result)
       //这里return obj没有意义,这里是个事件,时间返回的函数外面是接收不到的
       }
  }
//如果在fuction函数这里return obj也是不可以的,局部的变量无法在外部用
}

//使用封装工具
ajax({
   method:'GET',
   url:'http://+地址',
   data:'id = 1'
   async:true
})

此时的obj还不能调出来使用,这时解决方法:在函数中在传入一个函数 success,如果函数能进入if中实现结果的取用,将在函数中调用。

function ajas( {method='GET',url,data='',async=true,success} ){
  //"AJAX"(Asynchronous JavaScript and XML,异步 JavaScript 和 XML)
  //浏览器默认提供的对象,获取结果
  const xmlhttp = new XMLhttpRequest()
  //连接服务器
  xmlhttp.open(method,url,async)
  xmlhttp.send(data)

  //监听状态码,当状态码是200时
  xmlhttp.onreadystatechange = function(){
    //首先状态码必须是200,readyState代表xmlhttp加载过程
    if(xmlhttp.status == 200 && xmlhttp.readyState == 4){
       const result = xmlhttp.responseText
       //拿到数据后转化
          const obj = JSON.parse(result)
          success(Obj)
       }else if(404 500){
        error('失败')
       }
  }
}

//使用封装工具
ajax({
   method:'GET',
   url:'http://+地址',
   data:'id = 1'
   async:true,
   success:function(msg){
      console.log(msg)
   }
   //是否请求成功
   error:function(error){
    
   }   
})

 这样做有缺陷:回调地狱,无限制的在回调函数中执行任务,得到回调结果,层层嵌套,开发中要避免,不存在可读性。

//使用封装工具
ajax({
   method:'GET',
   url:'http://+地址',
   data:'id = 1'
   async:true,
   success:function(msg){
      console.log(msg)
      ajax({
         url:'http://+地址',
         data:msg.id,
         success(msg2){  
            ajax({
               url:'',
               data:msg.classesId
   }
   //是否请求成功
   error:function(error){
    
   }   
})

Promise

由上述Promise来解决异步编程的问题。 

//按照1234执行顺序来执行,因为promise本身是同步的,如果在promise中放入一个异步的代码,异步代码是需要花时间,异步代码不论花费多长时间,等到代码运行结束,成功或者失败都会存放在resolve,reject中。
console.log(1)
//resolve,reject 这两个参数是函数
const promise = new Promise((resolve,reject)=>{
console.log(2)
   //存放同步代码或者异步代码,这里主要存放异步代码
   ajas({
     url:'http://xxx',
     method:'POST',
     data:{id:1},
     success:(msg)=>{
        resolve(msg)
     },
     error:(error)=>{
        reject(error)
     }
  }) 
})

//then这个函数是异步的,只有resolve执行完毕,then才会执行
promise.then((result)=>{
   console.log(4)
})
.catch(error=>{

})


console.log(3)

 await和async

es7提出的一个新方案,可以等待promise的结果。

//resolve,reject 这两个参数是函数
const promise2 = new Promise((resolve,reject)=>{
   //存放同步代码或者异步代码,这里主要存放异步代码
   ajas({
     url:'http://xxx',
     method:'POST',
     data:{id:1},
     success:(msg)=>{
        resolve(msg)
     },
     error:(error)=>{
        reject(error)
     }
  }) 
})

 async function show(){
  const res1 = await promise1
  const res2 = await promise2
}

 axios工具

在前面代码的基础上,第三方工具axios做了一件事情,将axios代码和promise代码进行了封装,形成了一个完整的请求工具。

//封装格式
class Axios{
   baseURL =''
   get(){
      return new Promise (()=>{
       resolve(xxx)
       reject(xxx)
       })
   }

   post(){
   
   }
   creat(){
   
   }
}

export const axios = new Axios()

//代码中如何使用
import axios from 'axios'
//方法1:通过then拿到服务器响应回来的结果
axios.get('http://xxx').then(res=>{

{)
//方法2:通过await和async配合拿到服务器响应回来的结果
result = await axios.post('http://xxx')

作为一个第三方库,使用的时候需要先完成下包的操作,打开终端执行命令,ohpm 是一个包管理工具,用来管理鸿蒙提供的第三方模块。


网站公告

今日签到

点亮在社区的每一天
去签到