HarmonyOS @kit.NetworkKit 的 http 用法详解
HarmonyOS kit.NetworkKit 的 http 用法详解kit.NetworkKit的http是鸿蒙官方网络模块,零依赖、直接 import 就能用。本章整理http.createHttp()的完整用法、各种请求场景(GET / POST JSON / POST 表单 / GET 带 query)、Promise 链式调用、错误处理、资源释放。最小可运行示例import{http}fromkit.NetworkKit// 1. 创建请求实例lethttpRequesthttp.createHttp()// 2. 发请求httpRequest.request(http://192.168.0.126:8080/goods/select,{method:http.RequestMethod.GET}).then(resp{// 3. 成功回调if(resp.responseCode200){console.log(返回数据:,resp.result.toString())}}).catch((err:Error){// 4. 失败回调console.error(网络错误:,err.message)}).finally((){// 5. 释放资源 (必须做)httpRequest.destroy()})步骤关键 API必须性创建实例http.createHttp()必须,每次请求都要新建发请求.request(url, options)必须,返回 Promise成功处理.then(resp ...)至少要有一个 then失败处理.catch(err ...)推荐,不写错误会被吞资源释放.finally(() destroy())必须,不调有资源泄漏风险request 方法的参数httpRequest.request(url:string,options:{method?:http.RequestMethod// GET / POST / PUT / DELETE / ...header?:Object// 请求头(自定义 Content-Type / Authorization 等)extraData?:string|ArrayBuffer// 请求体(POST / PUT 才需要)expectDataType?:http.HttpDataType// 期望响应类型,影响 resp.result 的类型connectTimeout?:number// 连接超时毫秒,默认 60000readTimeout?:number// 读取超时毫秒,默认 60000usingCache?:boolean// 是否使用缓存,默认 true})最常用的就是methodheaderextraData三个。http.RequestMethod 枚举枚举值说明http.RequestMethod.GET获取资源,不带 bodyhttp.RequestMethod.POST创建资源,带 JSON bodyhttp.RequestMethod.PUT完整更新,带 bodyhttp.RequestMethod.DELETE删除,可带可不带 bodyhttp.RequestMethod.HEAD只取响应头http.RequestMethod.OPTIONS查询服务器支持的方法(CORS 预检)响应对象 resp 的结构{responseCode:number// HTTP 状态码: 200 / 404 / 500 等result:string|ArrayBuffer|Object// 响应体resultType:http.HttpDataType// 响应体的实际类型header:Object// 响应头cookies:string// 响应 Cookie}字段类型常见用法responseCodenumberif (resp.responseCode 200)判断成功result联合类型resp.result.toString()转字符串 JSON.parse解析headerObjectresp.header[content-type]看 MIME 类型场景 1: GET 请求(无参数)最简单的场景,直接拼 URL 即可。functiongetList(){lethttpRequesthttp.createHttp()httpRequest.request(http://192.168.0.126:8080/goods/select,{method:http.RequestMethod.GET}).then(resp{if(resp.responseCode200){// 后端返回 JSON 数组 → 反序列化 类型断言constlistJSON.parse(resp.result.toString())asGoods[]console.log(数据条数:,list.length)}}).finally(()httpRequest.destroy())}场景 2: GET 请求带 query 参数ArkTS 的 http 模块不会自动拼接 query 参数,需要自己拼到 URL 后面。functiondeleteById(id:number){lethttpRequesthttp.createHttp()httpRequest.request(${BASE_URL}/goods/delete?id${id},{method:http.RequestMethod.GET}).then(resp{/* ... */}).finally(()httpRequest.destroy())}多个参数时:constparams?name${encodeURIComponent(name)}page${page}size${size}httpRequest.request(${BASE_URL}/goods/search${params},{...})必须encodeURIComponent包含中文、空格、特殊字符的参数,否则 URL 会出问题。简单的纯数字 / 英文 id 可以省略。场景 3: POST 请求 JSON bodyRESTful 接口最主流的写法。三个关键参数:method/header/extraData。functioninsertGoods(name:string,price:number,desc:string,image:string){lethttpRequesthttp.createHttp()httpRequest.request(${BASE_URL}/goods/insert,{method:http.RequestMethod.POST,header:{Content-Type:application/json},extraData:JSON.stringify({name,price,desc,image})}).then(resp{if(resp.responseCode200){console.log(插入成功)}}).catch((err:Error){console.error(网络错误:,err.message)}).finally(()httpRequest.destroy())}关键点:参数值说明header[Content-Type]application/json必须显式设置,否则后端可能拒收extraDataJSON.stringify({...})必须显式序列化,不能直接传对象Spring Boot 的RequestBody Goods goods注解默认只解析 JSON,所以前端 Content-Type 必须是application/json才能正确反序列化。场景 4: POST 请求 表单数据如果后端用RequestParam而不是RequestBody,前端要发表单格式:httpRequest.request(${BASE_URL}/user/login,{method:http.RequestMethod.POST,header:{Content-Type:application/x-www-form-urlencoded},extraData:username${encodeURIComponent(username)}password${encodeURIComponent(password)}})数据格式是key1value1key2value2,和 query 字符串一样。场景 5: 加请求头(Authorization / Token 等)httpRequest.request(url,{method:http.RequestMethod.GET,header:{Content-Type:application/json,Authorization:Bearer${token},// JWT 鉴权X-Custom-Header:some-value// 任意自定义头}})场景 6: 设置超时默认连接和读取都是 60 秒,实际开发中通常调短一点:httpRequest.request(url,{method:http.RequestMethod.GET,connectTimeout:5000,// 5 秒连不上就失败readTimeout:10000// 10 秒没读完就失败})链式调用结构整个请求的标准结构:httpRequest.request(url,options).then(resp{// 处理响应if(resp.responseCode200){// 成功路径}else{// HTTP 状态码非 200(如 404 / 500)}}).catch((err:Error){// 网络层失败(连接失败 / 超时 / DNS 解析失败 等)// 注意:HTTP 状态码 404 / 500 不会进 catch,而是进 then 的 else 分支}).finally((){httpRequest.destroy()})进 then 的情况进 catch 的情况200 OK网络不通 / 连接被拒绝4xx 客户端错误超时5xx 服务器错误DNS 解析失败任何能拿到响应的情况任何拿不到响应的情况关键差异:HTTP 状态码不等于成功。只要服务器返回了响应,哪怕是 500,都会进 then。所以必须在 then 里手动判断responseCode 200。为什么必须 destroy()http.createHttp()创建的实例底层持有 socket / 内存 / 文件描述符等资源。如果不destroy():单次请求看不出问题但频繁创建不释放(比如列表刷新调几十次) → 资源泄漏 → 应用变卡 → 最终可能崩溃最佳实践:用.finally()保证无论成功失败都调用destroy()。.finally((){httpRequest.destroy()})完整封装(整合后端 CRUD 的常用模式)constBASE_URLhttp://192.168.0.126:8080// 通用 GETfunctionhttpGet(path:string):Promisestring{returnnewPromise((resolve,reject){letreqhttp.createHttp()req.request(${BASE_URL}${path},{method:http.RequestMethod.GET}).then(resp{if(resp.responseCode200){resolve(resp.result.toString())}else{reject(newError(HTTP${resp.responseCode}))}}).catch(reject).finally(()req.destroy())})}// 通用 POST JSONfunctionhttpPostJson(path:string,body:object):Promisestring{returnnewPromise((resolve,reject){letreqhttp.createHttp()req.request(${BASE_URL}${path},{method:http.RequestMethod.POST,header:{Content-Type:application/json},extraData:JSON.stringify(body)}).then(resp{if(resp.responseCode200){resolve(resp.result.toString())}else{reject(newError(HTTP${resp.responseCode}))}}).catch(reject).finally(()req.destroy())})}// 调用asyncfunctionloadAndInsert(){try{constlistTextawaithttpGet(/goods/select)constlistJSON.parse(listText)asGoods[]awaithttpPostJson(/goods/insert,{name:新商品,price:999,desc:测试,image:xm17})}catch(e){console.error(e)}}学习项目可以不封装,直接用裸 API;但如果接口数量大于 5 个就建议封装,避免每个调用点都重复写 createHttp destroy。常见错误对照表报错/现象原因修法Permission Denied缺ohos.permission.INTERNETmodule.json5 加权限 Clean 重装cleartext HTTP not permitted鸿蒙默认禁明文 HTTP改成 https,或加 cleartext 配置connect timeout/read timeout服务端未响应 / 防火墙拦截浏览器自测 检查防火墙HTTP 200 但 then 里 result 为空后端没返回 body看后端是不是直接 return 而没 return 数据JSON.parse: unexpected token后端返回的不是 JSONconsole.log(resp.result.toString())看实际返回catch 里 err.message 是null鸿蒙内部错误未透出看 IDE Log 里的 hilog,有详细堆栈后端收不到 POST 参数漏了Content-Typeheader 必须显式设application/json后端收到null字段字段名大小写不匹配鸿蒙extraData里 key 要和后端 bean 完全一致不止 http: rcp 模块更新更现代鸿蒙还有一个hms.collaboration.rcp模块(Remote Communication Kit),API 更现代(支持拦截器、自动 JSON、流式传输)。但是:需要 API 12学习曲线比 http 高当前学习项目用 http 已经够了如果以后要做正式项目、需要拦截器统一加 token / 统一错误处理,再考虑迁移到 rcp。