半亩花草 发表于 2024-9-18 21:07:38

【鸿蒙HarmonyOS】网络哀求http代码实现

在网络开发中,HTTP哀求是必不可少的一部分。在鸿蒙(HarmonyOS)开发中,同样需要处置处罚网络哀求,无论是与后端服务器交互照旧获取外部API的数据。下面是对鸿蒙开发中涉及到的HTTP模块——http模块,以及一个常用的第三方库——axios模块的总结。
HTTP协议概述

1. 根本概念



[*]哀求(Request):客户端向服务器发送的消息。
[*]响应(Response):服务器接收到哀求后返回给客户端的消息。
[*]消息格式:HTTP消息由报文头(Header)、状态行(Status Line)和可选的实体主体(Entity Body)构成。
2. 哀求报文结构



[*]哀求行:包含哀求方法、哀求URI和协议版本。GET /index.html HTTP/1.1

[*]哀求头:包含客户端的信息,如Accept-Language、User-Agent等。Accept-Language: zh-CN,zh;q=0.9
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3

[*]实体主体:可选部分,包含哀求的具体内容,如表单数据或文件上传。username=admin&password=123456

3. 响应报文结构



[*]状态行:包含HTTP版本、状态码及状态描述。HTTP/1.1 200 OK

[*]响应头:包含服务器的信息,如Content-Type、Date等。Content-Type: text/html; charset=UTF-8
Date: Thu, 01 Jan 2023 12:00:00 GMT

[*]实体主体:可选部分,包含响应的具体内容,如HTML文档。
4. 哀求方法



[*]GET:哀求指定的资源。
[*]POST:向指定资源提交数据进行处置处罚哀求(比方提交表单大概注册用户)。
[*]PUT:更换目标资源。
[*]DELETE:删除指定资源。
[*]HEAD:雷同于GET哀求,但只返回头部信息。
[*]OPTIONS:查询目标资源的通讯选项。
[*]PATCH:对资源进行部分更新。
5. 状态码



[*]1xx(信息响应类):指示哀求已被担当,需要进一步处置处罚。
[*]2xx(成功响应类):哀求已成功被服务器接收、理解,并担当。

[*]200 OK:成功。
[*]201 Created:创建成功。

[*]3xx(重定向类):需要客户端接纳进一步的操作来完成哀求。

[*]301 Moved Permanently:永久重定向。
[*]302 Found:临时重定向。

[*]4xx(客户端错误类):哀求中有错误,或哀求无法被服务器理解。

[*]400 Bad Request:哀求无效。
[*]401 Unauthorized:未经授权。
[*]403 Forbidden:禁止访问。
[*]404 Not Found:找不到资源。

[*]5xx(服务器错误类):服务器在处置处罚哀求的过程中发生了错误。

[*]500 Internal Server Error:内部服务器错误。
[*]503 Service Unavailable:服务不可用。

HTTP的工作原理


[*]建立连接:客户端与服务器之间建立TCP连接。
[*]发送哀求:客户端发送HTTP哀求到服务器。
[*]处置处罚哀求:服务器接收哀求,处置处罚哀求内容。
[*]发送响应:服务器根据处置处罚效果构建响应,并发送给客户端。
[*]关闭连接:完成响应后,默认情况下会关闭连接(HTTP/1.0),大概保持连接开放以供后续哀求使用(HTTP/1.1及以上版本)。
HTTP与HTTPS的区别



[*]安全性:HTTPS是在HTTP的基础上参加了SSL/TLS协议,用于加密传输的数据,增强安全性。
[*]端标语:HTTP默认端口为80,HTTPS默认端口为443。
[*]证书:HTTPS需要服务器端有数字证书支持,确保数据的完备性和机密性。
通过以上概述,你应该对HTTP协议有了更深入的理解。在实际开发中,根据差别的场景选择合适的哀求方法和状态码,对于构建健壮的网络应用程序至关紧张。
HarmonyOS HTTP模块

官方文档传送门
1. 概述

HarmonyOS提供了内置的http模块来实现HTTP哀求。此模块答应开发者以异步的方式发起HTTP哀求,支持GET、POST等多种HTTP方法。
根本用法

1. 导入

import { http } from '@kit.NetworkKit'
2. 创建哀求对象

const req = http.createHttp()
3. 发送哀求并获取响应

req.request('请求地址url')
.then((res: http.HttpResponse) => {
    AlertDialog.show({ message: JSON.stringify(res) })
})
注意事项



[*] 预览器:无需配置网络权限即可成功发送哀求。
[*] 模拟器:需要配置网络权限才能成功发送哀求。
[*] 真机:需要配置网络权限才能成功发送哀求。
[*] 在HarmonyOS中,你需要在module.json5文件中配置网络权限。以下是详细的配置示例:

{
"module": {
    "name": "entry",
    "type": "entry",
    "description": "$string:module_desc",
    "mainElement": "EntryAbility",
    "deviceTypes": [
      "phone",
      "tablet",
      "2in1"
    ],
    "deliveryWithInstall": true,
    "installationFree": false,
    "pages": "$profile:main_pages",
    "requestPermissions": [
      {
      "name": "ohos.permission.INTERNET"
      }
    ],
    "abilities": [
      {
      "name": "EntryAbility",
      "srcEntry": "./ets/entryability/EntryAbility.ets",
      "description": "$string:EntryAbility_desc",
      "icon": "$media:icon",
      "label": "$string:EntryAbility_label",
      "startWindowIcon": "$media:startIcon",
      "startWindowBackground": "$color:start_window_background",
      "exported": true,
      "skills": [
          {
            "entities": [
            "entity.system.home"
            ],
            "actions": [
            "action.system.home"
            ]
          }
      ]
      }
    ],
    "extensionAbilities": [
      {
      "name": "EntryBackupAbility",
      "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
      "type": "backup",
      "exported": false,
      "metadata": [
          {
            "name": "ohos.extension.backup",
            "resource": "$profile:backup_config"
          }
      ]
      }
    ]
}
}
// 代码示例import { http } from '@kit.NetworkKit'
const req = http.createHttp()
req.request('请求地址url')
.then((res: http.HttpResponse) => {
    AlertDialog.show({ message: JSON.stringify(res) })
})
2. 主要方法

   通过一个图书管理案例来详细了解一下http哀求数据的根本使用,因为需要用到接口,我使用的是黑马程序员提供的在线接口文档链接仅供学习
https://i-blog.csdnimg.cn/direct/591ac33452e9421494415c1a10362910.png
完成效果
https://i-blog.csdnimg.cn/direct/1ff8900bc0584f4a838e2aca6b29b7de.gif#pic_center
3. 示例代码


export interface IBook{
/**
   * 响应数组
   */
data: iBook[];
/**
   * 响应消息
   */
message: string;

}

export interface IBookdetail{
/**
   * 响应数组
   */
data: iBook;
/**
   * 响应消息
   */
message: string;
}
export interface iBook {
/**
   * 图书作者
   */
author: string;
/**
   * 图书名字
   */
bookname: string;
/**
   * 图书id
   */
id: number;
/**
   * 图书出版社
   */
publisher: string;
}

exportconst creator='艾宝宝'
获取-图书列表 GET &&删除-图书 DELETE
import { IBook, iBook } from './databook'import { http } from '@kit.NetworkKit'
import router from '@ohos.router'import { promptAction } from '@kit.ArkUI'@Entry@Componentstruct MyBook {@State ISfree: boolean = false@State books: iBook[] = []/**   * 页面显示时调用的方法   * 该方法在页面被显示时触发,用于获取书籍信息   */onPageShow(): void {    // 调用getbook方法获取书籍信息    this.getbook()      // 将返回的效果分析为IBook对象      .then(res => {      let obj: IBook = JSON.parse(res.result.toString())      // 将分析后的书籍数据赋值给books属性      this.books = obj.data      })}/**   * 获取书籍信息的方法   * 该方法用于发起网络哀求,获取指定创建者的书籍信息   * @returns 返回一个Promise对象, resolve时携带HTTP响应   */getbook() {    // 创建HTTP哀求对象    const req = http.createHttp()
    // 发起网络哀求,获取书籍信息    return req.request('https://hmajax.itheima.net/api/books?creator=' + encodeURIComponent('艾宝宝'))}      //顶部@Buildertop() {    Row() {      Image($r('app.media.ic_public_drawer_filled'))      .width(30)      //点击弹窗,点击确认全部删除      .onClick(()=>{         promptAction.showDialog({               title: '提示',               message: '确定全部删除吗?',               buttons: [                   { text: '取消', color: '#ff161616' },                   { text: '确认', color: '#ff2156c1' }               ]         }).then(res=>{             // 根据响应的索引实行差别的操作             if (res.index == 1) {               // 创建HTTP哀求对象               const req = http.createHttp()
               // 向指定URL发送DELETE哀求以删除数据               req.request('https://hmajax.itheima.net/api/books', {               method: http.RequestMethod.DELETE               })               .then(res => {                   // 分析响应效果,根据id数组中的每个id向服务器发送删除哀求                   this.books.map((item)=>{                     returnreq.request('https://hmajax.itheima.net/api/books/' + item.id, {                         method: http.RequestMethod.DELETE                     })                     .then(res => {                         // 分析响应效果,显示提示信息                         let obj: IBook = JSON.parse(res.result.toString())                         promptAction.showToast({                           message: `${obj.message}`                         })                         // 重新获取数据                         this.getbook()                           .then(res => {                           let obj: IBook = JSON.parse(res.result.toString())                           // 更新当地数据                           this.books = obj.data                           })                     })                   })               })             }         })      })      Text(`我的书架`).fontSize(25)      .fontWeight(FontWeight.Bold)      Image($r('app.media.ic_public_add'))      .width(30)      .onClick(() => {          router.pushUrl({            url: '/pages/addbook'.slice(1)          })      })    }.width('100%')    .padding(10)    .justifyContent(FlexAlign.SpaceBetween)    .border({ width: { bottom: 1 }, color: '#80000000' })}//图书列表@Builderlist() {    List() {      ForEach(this.books, (item: iBook, index: number) => {      ListItem() {          Row({ space: 10 }) {            Image($r('app.media.ic_public_cover'))            .height(100)            Column({ space: 20 }) {            Column({ space: 10 }) {                Text(`书名:` + item.bookname).width('100%').fontWeight(FontWeight.Bold)                  .fontSize(18)                Text(`作者:` + item.author).width('100%')                  .fontSize(14)                  .fontColor('#666666')            }            Text(`出版社:` + item.publisher).width('100%')                .fontSize(14)                .fontColor('#666666')            }            .layoutWeight(1)          }.width('100%').height(100)      }.padding(10)      .swipeAction({ end: this.dle(item.id), })      .onClick(() => {          router.pushUrl({            url: '/pages/alterbook'.slice(1),            params: {            id: item.id            }          })      })      })    }.layoutWeight(1).scrollBar(BarState.Off)}//删除图标@Builderdle(id: number) {    Column() {      Text(`删除`)      .fontColor('#ffffff')      .fontWeight(FontWeight.Bold)    }.width(70)    .height('100%')    .backgroundColor('red')    .justifyContent(FlexAlign.Center)    .onClick(()=>{   promptAction.showDialog({    title: '提示',    message: '确定删除吗?',    buttons: [      { text: '确定', color: '#ff164ae0' },      { text: '取消', color: '#ff1c1919' }    ]})      .then(res=>{            //AlertDialog.show({message:JSON.stringify(res,null,2)})          //点击确定删除 ---索引次序从0开始 左边是0          if (res.index == 0) {            const req = http.createHttp()
            req.request('https://hmajax.itheima.net/api/books/' + id, {            method: http.RequestMethod.DELETE            })            .then(res => {                let obj: IBook = JSON.parse(res.result.toString())                promptAction.showToast({                  message: `${obj.message}`                })                this.getbook()                  .then(res => {                   let obj: IBook = JSON.parse(res.result.toString())                  this.books = obj.data                  })            })          }      })    })}build() {      Column() {      //      this.top()      //正在加载的动画      if (this.books.length == 0) {          this.loading()      }      //      this.list()      }      .padding(10)      .width('100%')      .height('100%')}//加载中占位图@Builderloading() {    Row() {      LoadingProgress()      .width(50)      Text(`加载中...`)    }}} 新增-图书 POST
// 导入创建者import { creator, IBook } from './databook'import { promptAction, router } from '@kit.ArkUI'import { http } from '@kit.NetworkKit'
/* * 步调 * 1. 非空验证 -> 轻提示用户 * ✔️2. 获取表单的值 -> 已经使用了$$完成 * 3. 发出POST哀求将数据提交给服务器 * 4. 返回图书列表页面 * * */@Entry@Componentstruct addPage {@State bookname: string = ''@State author: string = ''@State publisher: string = ''// 新增的addSubmit() {    //1. 非空验证 -> 轻提示用户    if (this.bookname == '' || this.author == '' || this.publisher == '') {      promptAction.showToast({ message: '图书名,作者,出版社均非空' })      return //阻止下面代码继续实行    }    // 3. 发出POST哀求将数据提交给服务器    const req = http.createHttp()
    req.request('https://hmajax.itheima.net/api/books', {      method: http.RequestMethod.POST,      header: {      'Content-Type': 'application/json'      },      extraData: {      bookname: this.bookname,      author: this.author,      publisher: this.publisher,      creator: creator      }    }).then(res => {      let obj: IBook = JSON.parse(res.result.toString())      // 提示用户新增的效果      promptAction.showToast({ message: obj.message })      // 4. 返回图书列表页面      // ✨✨注意:通过router.back()返回的页面是不会触发aboutToAppear这个函数的      // 需要将其改成 onPageShow ,所以我们需要改造 BookListPage.ets中的生命周期方法      // pushUrl -> 页面栈中每次都新增一个页面,最多只能32个,所以这里使用back方法来节省页面栈      router.back()    })}build() {    Navigation() {      Column({ space: 10 }) {      Row() {          Text('图书名称:')          TextInput({ placeholder: '请输入图书名字', text: $$this.bookname })      }      Row() {          Text('图书作者:')          TextInput({ placeholder: '请输入作者名字', text: $$this.author })      }      Row() {          Text('图书出版社:')          TextInput({ placeholder: '请输入出版社名字', text: $$this.publisher })      }      Button({ type: ButtonType.Normal }) {          Text('保存')            .fontColor(Color.White)            .fontWeight(800)      }      .width('100%')      .height(40)      .borderRadius(8)      .onClick(() => {          // 调用新增逻辑方法          this.addSubmit()      })      }      .height('100%')      .width('100%')      .padding(10)    }    .title('新增图书')    .titleMode(NavigationTitleMode.Mini)}} 修改-图书 PUT
import router from '@ohos.router'import { creator, IBook, IBookdetail } from './databook'import { http } from '@kit.NetworkKit'
import { promptAction } from '@kit.ArkUI'interface BookId {id: number}@Entry@Componentstruct Alterbook {req = http.createHttp()@State bookid: number = 0creator: string = creator@State bookname: string = ''@State author: string = ''@State publisher: string = ''// 页面加载时,获取图书id,通过id获取图书信息id(路由传参)aboutToAppear(): void {    let obj = router.getParams() as BookId    this.bookid = obj.id    this.req.request('https://hmajax.itheima.net/api/books/' + this.bookid, {})      .then(res => {      let book: IBookdetail = JSON.parse(res.result.toString())      this.bookname = book.data.bookname      this.author = book.data.author      this.publisher = book.data.publisher      })}// creator: string = creatorbuild() {    Navigation() {      Column({ space: 10 }) {      Row() {          Text(`图书名称:`)          TextInput({            placeholder: '请输入图书名称', text: $$this.bookname,          }).layoutWeight(1)            .backgroundColor('#fff')      }.border({ width: { bottom: 1 }, color: '#ccc' })      Row() {          Text(`图书作者:`)          TextInput({            placeholder: '请输入图书作者',            text: $$this.author,          }).layoutWeight(1).backgroundColor('#fff')            .backgroundColor('#fff')      }.border({ width: { bottom: 1 }, color: '#ccc' })      Row() {          Text(`图书出版社:`)          TextInput({            placeholder: '请输入出版社',            text: $$this.publisher,          }).layoutWeight(1).backgroundColor('#fff')      }.border({ width: { bottom: 1 }, color: '#ccc' })      Button({ type: ButtonType.Normal }) {          Text(`保存`)            .fontSize(18)            .fontColor('#fff')            .fontWeight(FontWeight.Bold)      }.width('100%').borderRadius(10)      //将页面数据重新发送哀求到服务器,修改完毕      .onClick(() => {          if (this.bookname == '' || this.author == '' || this.publisher == '') {            promptAction.showToast({            message: `请输入完备信息`,            bottom: 350            })          } else {            // 创建一个HTTP哀求对象            const req = http.createHttp()
            // 发送PUT哀求以更新书籍信息            req.request('https://hmajax.itheima.net/api/books/' + this.bookid, {            // 设置哀求方法为PUT            method: http.RequestMethod.PUT,            // 设置哀求头,指定内容类型为JSON            header: {                'content-type': 'application/json'            },            // 设置哀求体,包含需要更新的书籍信息            extraData: {                bookname: this.bookname,                author: this.author,                publisher: this.publisher,                creator: creator            }            // 哀求发送完成后实行的回调函数            // 这里可以处置处罚响应数据大概处置处罚错误            }).then(res => {            let obj: IBook = JSON.parse(res.result.toString())            promptAction.showToast({                message: `${obj.message}`,                bottom: 350            })            router.back()            })          }      })      .height(38)      }.padding(15)    }    .title('编辑图书')    .titleMode(NavigationTitleMode.Mini)}} Axios模块

1. 概述

Axios 是一个基于Promise的HTTP客户端,可以在浏览器和Node.js中使用。虽然HarmonyOS不是直接支持Node.js环境,但是可以通过npm安装axios并在HarmonyOS的应用中使用。
参考链接
2. 优点



[*]基于Promise:可以使用async/await语法编写更简洁的异步代码。
[*]支持浏览器和Node.js:具有良好的跨平台本领。
[*]易于使用:API简朴易懂,文档丰富。
3. 安装

在HarmonyOS应用开发环境中,可以使用npm来安装axios:
# 安装
ohpm i @ohos/axios

# 卸载
ohpm uninstall @ohos/axios
使用示例

使用前在demo中entry–>src–>main–>ets–>common–>Common.ets文件中改为正确的服务器所在,在entry–>src–>main–>resources–>rawfile目录下添加正确的证书,才可正常的使用demo。
发起一个 GET 哀求
axios支持泛型参数,由于ArkTS不再支持any类型,需指定参数的具体类型。 如:axios.get<T = any, R = AxiosResponse, D = any>(url)


[*]T: 是响应数据类型。当发送一个 POST 哀求时,客户端大概会收到一个 JSON 对象。T 就是这个 JSON 对象的类型。默认情况下,T 是 any,这意味着可以接收任何类型的数据。
[*]R: 是响应体的类型。当服务器返回一个响应时,响应体通常是一个 JSON 对象。R 就是这个 JSON 对象的类型。默认情况下,R 是 AxiosResponse,这意味着响应体是一个 AxiosResponse 对象,它的 data 属性是 T 类型的
[*]D: 是哀求参数的类型。当发送一个 GET 哀求时,大概会在 URL 中添加一些查询参数。D 就是这些查询参数的类型。参数为空情况下,D 是 null类型。
import axios from '@ohos/axios'
interface userInfo{
id: number
name: string,
phone: number
}

// 向给定ID的用户发起请求
axios.get<userInfo, AxiosResponse<userInfo>, null>('/user?ID=12345')
.then((response: AxiosResponse<userInfo>)=> {
// 处理成功情况
console.info("id" + response.data.id)
console.info(JSON.stringify(response));
})
.catch((error: AxiosError)=> {
// 处理错误情况
console.info(JSON.stringify(error));
})
.then(()=> {
// 总是会执行
});

// 上述请求也可以按以下方式完成(可选)
axios.get<userInfo, AxiosResponse<userInfo>, null>('/user', {
params: {
    ID: 12345
}
})
.then((response:AxiosResponse<userInfo>) => {
console.info("id" + response.data.id)
console.info(JSON.stringify(response));
})
.catch((error:AxiosError) => {
console.info(JSON.stringify(error));
})
.then(() => {
// 总是会执行
});

// 支持async/await用法
async function getUser() {
try {
      const response:AxiosResponse = await axios.get<string, AxiosResponse<string>, null>(this.getUrl);
      console.log(JSON.stringify(response));
      } catch (error) {
    console.error(JSON.stringify(error));
}
}
发送一个 POST 哀求
interface user {
firstName: string,
lastName: string
}
   axios.post<string, AxiosResponse<string>, user>('/user', {
   firstName: 'Fred',
   lastName: 'Flintstone'
   })
   .then((response: AxiosResponse<string>) => {
   console.info(JSON.stringify(response));
   })
   .catch((error) => {
console.info(JSON.stringify(error));
});
发起多个并发哀求
const getUserAccount = ():Promise<AxiosResponse> => {
      return axios.get<string, AxiosResponse<string>, null>('/user/12345');
    }

const getUserPermissions = ():Promise<AxiosResponse> => {
      return axios.get<string, AxiosResponse<string>, null>('/user/12345/permissions');
    }

Promise.all<AxiosResponse>()
.then((results:AxiosResponse[]) => {
      const acct = results.data as string;
      const perm = results.data as string;
      });
使用说明

axios API

通过向 axios 传递相干配置来创建哀求

axios(config)

// 发送一个get请求
axios<string, AxiosResponse<string>, null>({
method: "get",
url: 'https://www.xxx.com/info'
}).then((res: AxiosResponse) => {
console.info('result:' + JSON.stringify(res.data));
}).catch((error: AxiosError) => {
console.error(error.message);
})
axios(url[, config])

// 发送一个get请求(默认请求方式)
axios.get<string, AxiosResponse<string>, null>('https://www.xxx.com/info', { params: { key: "value" } })
.then((response: AxiosResponse) => {
console.info("result:" + JSON.stringify(response.data));
})
.catch((error: AxiosError) => {
console.error("result:" + error.message);
});
哀求方法的 别名方式 来创建哀求

为方便起见,为全部支持的哀求方法提供了别名。


[*]axios.request(config)
[*]axios.get(url[, config])
[*]axios.delete(url[, config])
[*]axios.post(url[, data[, config]])
[*]axios.put(url[, data[, config]])
   注意: 在使用别名方法时, url、method、data 这些属性都不必在配置中指定。
// 发送get请求
axios.get<string, AxiosResponse<string>, null>('https://www.xxx.com/info', { params: { key: "value" } })
.then((response: AxiosResponse) => {
console.info("result:" + JSON.stringify(response.data));
})
.catch((error: AxiosError) => {
console.error("result:" + error.message);
});
axios 实例

创建一个实例

您可以使用自界说配置新建一个实例。
axios.create()
const instance = axios.create({
baseURL: 'https://www.xxx.com/info',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
实例方法



[*]axios#request(config)
[*]axios#get(url[, config])
[*]axios#delete(url[, config])
[*]axios#post(url[, data[, config]])
[*]axios#put(url[, data[, config]])
4. 图书案例示例代码–Axios


export interface iBookResponse {
/**
   * 响应数组
   */
data: iBookInfo[];
/**
   * 响应消息
   */
message: string;
}
export constcreator: string = 'baba'

// 按需导出
export interface iBookInfo {
/**
   * 图书作者
   */
author: string;
/**
   * 图书名字
   */
bookname: string;
/**
   * 图书id
   */
id: number;
/**
   * 图书出版社
   */
publisher: string;
}

获取-图书列表 GET &&
删除-图书 DELETE

import axios, { AxiosResponse } from '@ohos/axios'
import { iBookResponse, iBookInfo, creator } from './models'
import router from '@ohos.router'
import { promptAction } from '@kit.ArkUI'


const req = axios.create()

@Entry
@Component
struct Index {
@State bookList: iBookInfo[] = []
creator: string = creator

//-------------------------
onPageShow(): void {
    this.getList()
}

//-----------------请求数据渲染到列表
async getList() {
    // 发起GET请求以获取图书数据
    let res: AxiosResponse<iBookResponse> =
      await req.request({
      url: 'https://hmajax.itheima.net/api/books',
      method: 'get',
      params: {
          creator: creator
      }
      })
    // 将请求响应中的图书数据赋值给bookList属性
    this.bookList = res.data.data
    //AlertDialog.show({message:JSON.stringify(res.data)})
}

// 1. 我的书架
@Builder
MyBook() {
    Row() {
      Image($r('app.media.ic_public_drawer_filled'))
      .height(20)//---------------点击全部删除
      .onClick(async () => {
          promptAction.showDialog({
            title: '提示',
            message: '确定删除吗?',
            buttons: [
            { text: '确定', color: '#ff164ae0' },
            { text: '取消', color: '#ff1c1919' }
            ]
          }) //根据点击结果,执行不同的操作
          //循环数组,每次根据id删除
         if (res.index == 0) {
          for (let i = 0; i < this.bookList.length; i++) {
            let res: AxiosResponse<iBookResponse> =
            await req.request({
                url: 'https://hmajax.itheima.net/api/books/' + this.bookList.id,
                method: 'delete'
            })
          }
          }
          //刷新列表 提示
          AlertDialog.show({ message: '全部删除成功' })
          this.getList()

      })
      Text('我的书架')
      .fontSize(20)
      .fontWeight(800)
      Image($r('app.media.ic_public_add'))
      .height(20)
      .onClick(() => {
          router.pushUrl({
            url: '/pages/Mbook/addPage'.slice(1),
          })
      })
    }
    .width('100%')
    .justifyContent(FlexAlign.SpaceBetween)
    .padding(10)
    .border({ width: { bottom: 1 }, color: { bottom: 'rgba(0,0,0,0.2)' } })
}
// 2. 书籍列表
@Builder
BookList() {
    List() {
      ForEach(this.bookList, (item: iBookInfo, index: number) => {
      ListItem() {
          // 布局
          Row({ space: 10 }) {
            Image($r('app.media.ic_public_cover'))
            .width(100)
            Column({ space: 25 }) {
            Column() {
                Text('书名:' + item.bookname)
                  .width('100%')
                  .fontSize(20)
                  .fontWeight(800)
                Text('作者:' + item.author)
                  .width('100%')
                  .fontSize(14)
                  .fontWeight(600)
                  .fontColor('rgba(0,0,0,0.4)')
                  .padding({ top: 5 })
            }
            Text('出版社:' + item.publisher)
                .width('100%')
                .fontWeight(600)
                .fontColor('rgba(0,0,0,0.4)')
            }
            .layoutWeight(1)
          }
          .padding(10)
          //-----------点击跳转编辑
          .onClick(() => {
            router.pushUrl({
            url: 'pages/Mbook/BjPage',
            params: {
                bookid: item.id
            }
            })
          })
      }
      .swipeAction({
          end: this.delBuilder(item.id)
      })
      })
    }
}

// 3. 删除书籍的构建函数
@Builder
delBuilder(id: number) {
    Column() {
      Text('删除')
      .backgroundColor(Color.Red)
      .fontColor(Color.White)
      .height('100%')
      .width(60)
      .textAlign(TextAlign.Center)
    }
    .padding(10)
    //点击提示确认删除
    .onClick(() => {
      promptAction.showDialog({
      title: '提示',
      message: '确定删除吗?',
      buttons: [
          { text: '确定', color: '#ff164ae0' },
          { text: '取消', color: '#ff1c1919' }
      ]
      })//根据点击结果,执行不同的操作
      .then(async (res) => {
          if (res.index == 0) {
            //删除
            let res: AxiosResponse<iBookResponse> =
            await req.request({
                url: 'https://hmajax.itheima.net/api/books/' + id,
                method: 'delete'
            })
            //删除成功,提示,刷新列表
            promptAction.showToast({
            message: '删除成功'
            })
            this.getList()
          }
      })
    })
}
build() {
    Column() {
      // 1. 我的书架
      this.MyBook()
      // 2. 书籍列表
      this.BookList()
    }
    .height('100%')
    .width('100%')
}
}
新增-图书 POST
// 导入创建者
import axios, { AxiosResponse } from '@ohos/axios'
import { creator, iBookInfo, iBookResponse } from './models'
import { promptAction, router } from '@kit.ArkUI';

// POST请求体数据类型
export interface iReqeustBody {
/**
   * 新增图书作者
   */
author: string;
/**
   * 新增图书名字
   */
bookname: string;
/**
   * 新增图书创建者,自己的外号,和获取图书时的外号相同
   */
creator: string;
/**
   * 新增图书出版社
   */
publisher: string;
}
@Entry
@Component
struct addPage {
@State bookname: string = ''
@State author: string = ''
@State publisher: string = ''
creator: string = creator
build() {
    Navigation() {
      Column({ space: 10 }) {
      Row() {
          Text('图书名称:')
          TextInput({ placeholder: '请输入图书名字', text: $$this.bookname })
      }

      Row() {
          Text('图书作者:')
          TextInput({ placeholder: '请输入作者名字', text: $$this.author })
      }

      Row() {
          Text('图书出版社:')
          TextInput({ placeholder: '请输入出版社名字', text: $$this.publisher })
      }

      Button({ type: ButtonType.Normal }) {
          Text('保存')
            .fontColor(Color.White)
            .fontWeight(800)
      }
      .width('100%')
      .height(40)
      .borderRadius(8)
      //保存更新图书
      .onClick(async () => {
          // 调用接口保存图书
          // 1. 创建一个请求对象
          let req = axios.create()
          // 2. 发送请求
          if (this.bookname == '' || this.author == '' || this.publisher == '') {
            promptAction.showToast({
            message: `请输入完整信息`,
            bottom: 350
            })
          } else {
            let res: AxiosResponse<iBookResponse> =
            await req.request({
                url: 'https://hmajax.itheima.net/api/books',
                method: 'post',
                data: {
                  bookname: this.bookname,
                  author: this.author,
                  publisher: this.publisher,
                  creator: creator
                } as iReqeustBody
            })
            // 提示然后返回
            promptAction.showToast({
            message: `${res.data.message}`,
            bottom: 350
            })
            router.back()
          }
      })
      }
      .height('100%')
      .width('100%')
      .padding(10)
    }
    .title('新增图书')
    .titleMode(NavigationTitleMode.Mini)
}
}
修改-图书 PUT
// 导入创建者
import { creator, iBookInfo, iBookResponse, } from './models'
import { router } from '@kit.ArkUI'
import axios, { AxiosResponse } from '@ohos/axios'

interface iRouterParams {
bookid: number
}
interface iBookInfo1 {
/**
   * 图书作者
   */
author: string;
/**
   * 图书名字
   */
bookname: string;
/**
   * 图书创建者,写上自己名字-管理自己的数据
   */
creator: string;
/**
   * 图书出版社
   */
publisher: string;
}
export interface Putbook{
data:iBookInfo1
}

const req = axios.create()

@Entry
@Component
struct addPage {
@State bookname: string = ''
@State author: string = ''
@State publisher: string = ''
bookid: number = 0

aboutToAppear(): void {
    //得到传过来的id
    let routerObj = router.getParams() as iRouterParams
    this.bookid = routerObj.bookid

    this.loadBook()
}

// 1. 回显图书数据
async loadBook() {
    try {
      // 此处编写代码
      let res: AxiosResponse<Putbook> = await req.request({
      url: 'https://hmajax.itheima.net/api/books/' + this.bookid,
      method: 'get',

      })
      //AlertDialog.show({message:'获取图书数据成功'})
      this.bookname = res.data.data.bookname
      this.author = res.data.data.author
      this.publisher = res.data.data.publisher
    } catch (err) {
      console.error('err--->', JSON.stringify(err).slice(0,800))
    }
}

build() {
    Navigation() {
      Column({ space: 10 }) {
      Row() {
          Text('图书名称:')
          TextInput({ placeholder: this.bookname, text: $$this.bookname })
      }
      Row() {
          Text('图书作者:')
          TextInput({ placeholder: this.author, text: $$this.author })
      }
      Row() {
          Text('图书出版社:')
          TextInput({ placeholder: this.publisher, text: $$this.publisher })
      }
      Button({ type: ButtonType.Normal }) {
          Text('保存')
            .fontColor(Color.White)
            .fontWeight(800)
      }
      .width('100%')
      .height(40)
      .borderRadius(8)
//---------------点击修改并保存数据
      .onClick(async () => {
          let res: AxiosResponse<iBookResponse> =
            await req.request({
            url: 'https://hmajax.itheima.net/api/books/' + this.bookid,
            method: 'put',
            data: {
            bookname: this.bookname,
            author: this.author,
            publisher: this.publisher,
            creator: creator
            } as iBookInfo1
          })
          AlertDialog.show({message:'修改图书数据成功'})
          router.back()
      })
      }
      .height('100%')
      .width('100%')
      .padding(10)
    }
    .title('编辑图书')
    .titleMode(NavigationTitleMode.Mini)
}
}
5. 配置和拦截器

loding···
【http封装】 - 封装request泛型方法

我们发现网络哀求的代码许多,且有些相似之处,我们把GET,POST进行封装之后哀求就变得非常简朴了,我把封装的类放下面:
新建一个.ets文件
loading·····
(更新中···)
import axios, { AxiosResponse, AxiosError, AxiosRequestConfig } from '@ohos/axios'
import { iLoginUserModel, iResponseModel } from '../models/datamodel'
import { promptAction, router } from '@kit.ArkUI'

// 1. 准备一个axios的对象实例,同时设置好baseUrl
const req = axios.create({
baseURL: 'https://api-harmony-teach.itheima.net/'
})

export class HdHttp {
// 这个方法给外面专门做get请求调用的
static async Get<T>(url: string, paramsOrData?: object) {
return await HdHttp.request<T>('GET', url, paramsOrData)
}

// 这个方法给外面专门做post请求调用的
static async Post<T>(url: string, paramsOrData?: object) {
return await HdHttp.request<T>('POST', url, paramsOrData)
}

/*
method:表示服务器的请求方法,Get,POST,PUT,Delete
url:代表的是服务器的url路径(不包含基本域名地址) ,例如:hm/studyInfo
* paramsOrData:请求传参,可选
*
* T:代表的是服务器响应数据中的 data这个属性的类型
* */
private static async request<T>(method: string, url: string, paramsOrData?: object) {
try {
    //   1. 使用req来发送请求
    let reqConfig: AxiosRequestConfig = {
      method: method,
      url: url, //是请求接口的url路径部分,并且不带有/
    }
    // 2. 分请求类型来决定传参参数是parmas还是data
    if (method == 'GET') {
      reqConfig.params = paramsOrData
    } else {
      reqConfig.data = paramsOrData
    }

    // 3. 在请求前在header中携带token
    // 获取token
    let user = AppStorage.get<iLoginUserModel>('user')
    if (user && user.token) {
      reqConfig.headers = {
      'Authorization': `Bearer ${user.token}`
      }
    }

    let res: AxiosResponse<iResponseModel<T>> = await req.request(reqConfig)

    // 4. 处理服务器响应体中的code值为非10000的情况
    if (res.data.code != 10000) {
      //将服务器的逻辑问题信息提示给用户
      promptAction.showToast({ message: res.data.message })
      return Promise.reject(res.data.message) //传递给外部调用者的 catch()中的信息
    }
    //   3. 返回结果(返回的是服务器的响应报文体的数据)
    return res.data

} catch (err) {
    //当服务器的http状态码为非200,就会执行catch
    let errObj: AxiosError = err
    // 判断服务器的响应状态码如果是401,表示token失效,此时应该提示用户和跳转到登录页面
    if (errObj.response?.status == 401) {
      promptAction.showToast({ message: '登录已失效,请重新登录' })
      router.replaceUrl({ url: 'pages/LoginPage' })
    } else {
      //提示用户是什么错误即可
      promptAction.showToast({ message: '网络异常:' + errObj.message })
    }
    // AlertDialog.show({ message: 'err:' + JSON.stringify(errObj.response?.status, null, 2) })
    return Promise.reject(errObj.message) //传递给外部调用者的 catch()中的信息 外面使用者使用try{}catch(err){}
}
}
}
调用封装好的类进行代码实现
loading·····
总结



[*]HarmonyOS内置的HTTP模块:提供了根本的HTTP哀求功能,适合简朴的网络通讯需求。
[*]Axios:提供了更丰富的功能和更好的用户体验,尤其是对于需要更复杂哀求处置处罚的应用来说,是一个不错的选择。
选择哪个模块取决于你的具体需求和偏好。假如你的应用需要与Web服务细密集成并且需要更多的功能,那么axios大概是更好的选择;而对于简朴的HTTP哀求,HarmonyOS自带的HTTP模块就充足了。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 【鸿蒙HarmonyOS】网络哀求http代码实现