1、鸿蒙中如何进行网络请求
1.1 三方库请求
-
@ohos/axios
-
@ohos/retrofit
-
@ohos/httpclient
1.2 鸿蒙原生请求
-
@ohos.net.http
2、ArkTs请求模块@ohos.net.http
本模块提供HTTP数据请求能力。应用可以通过HTTP发起一个数据请求,支持常见的GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT方法。
3、@ohos.net.http请求流程
-
http.createHttp(创建请求实例任务);
-
request(请求);
-
destroy(中断请求);
-
on(订阅HTTP Response Header 事件);
-
off(取消订阅HTTP Response Header 事件);
-
once(订阅HTTP Response Header 事件,但是只触发一次);
4、预览效果
5、封装@ohos.net.http
5.1 函数式
5.1.1 封装
import http from '@ohos.net.http';
export interface httpOptions {
timeOut?: number;
ContentType?: string;
header?: Object;
state?: string;
callBack?: Function;
}
const HTTP_READ_TIMEOUT = 60000;
const HTTP_CONNECT_TIMEOUT = 60000;
const CONTENT_TYPE = 'application/json'
export function httpRequest(
url: string,
method: http.RequestMethod = http.RequestMethod.GET,
params?: string | Object | ArrayBuffer,
options?: httpOptions
): Promise<ResponseResult> {
const request = http.createHttp();
// 处理状态
if(options?.state) {
switch (options.state) {
case 'on':
request.on('headersReceive', (header) => options.callBack(header));
break;
case 'once':
request.on('headersReceive', (header) => options.callBack(header));
break;
case 'off':
request.off('headersReceive');
break;
case 'destroy':
request.destroy();
break;
default:
break;
}
return;
}
// 处理请求
const responseResult = request.request(url, {
// 超时时间
readTimeout: options?.timeOut || HTTP_READ_TIMEOUT,
connectTimeout: options?.timeOut || HTTP_CONNECT_TIMEOUT,
method,
extraData: params || {},
header: options?.header || {
'Content-Type': options?.ContentType || CONTENT_TYPE
},
});
let serverData: ResponseResult = new ResponseResult();
// Processes the data and returns.
return responseResult.then((data: http.HttpResponse) => {
if (data.responseCode === http.ResponseCode.OK) {
// Obtains the returned data.
let result = `${data.result}`;
let resultJson: ResponseResult = JSON.parse(result);
serverData.data = resultJson;
serverData.code = 'success';
serverData.msg = resultJson?.msg;
} else {
serverData.msg = `error info & ${data.responseCode}`;
}
return serverData;
}).catch((err) => {
serverData.msg = `${err}`;
return serverData;
})
}
export class ResponseResult {
/**
* Code returned by the network request: success, fail.
*/
code: string;
/**
* Message returned by the network request.
*/
msg: string | Resource;
/**
* Data returned by the network request.
*/
data: string | Object | ArrayBuffer;
constructor() {
this.code = '';
this.msg = '';
this.data = '';
}
}
export default httpRequest;
5.1.2 使用
import httpRequest from '../../utils/requestHttp';
interface resultType {
resultcode: string;
reason: string;
result: resultValType | null;
error_code: string;
}
interface resultValType {
city: string;
realtime: realtimeType;
future: Object;
}
interface realtimeType {
temperature: string;
humidity: string;
info: string;
wid: string;
direct: string;
power: string;
aqi: string;
}
@Extend(Text) function textStyle() {
.fontColor(Color.White)
.margin({
left: 12
})
}
@Entry
@Component
struct httpPages {
@State html: resultValType = {
city: '',
realtime: {
temperature: '',
humidity: '',
info: '',
wid: '',
direct: '',
power: '',
aqi: '',
},
future: undefined
};
@State url: string = "http://apis.juhe.cn/simpleWeather/query?key=397c9db4cb0621ad0313123dab416668&city=西安";
@Styles weatherStyle() {
.width('100%')
.padding(6)
.backgroundColor(Color.Green)
.borderRadius(8)
}
build() {
Column({space: 10}) {
Button("请求数据")
.onClick(() => {
this.httpRequest();
})
Column() {
Text(this.html.city || '--').textStyle().fontWeight(FontWeight.Bold)
}.weatherStyle().alignItems(HorizontalAlign.Start)
Column() {
Text(this.html.realtime.temperature || '--').textStyle()
}.weatherStyle().alignItems(HorizontalAlign.Start)
Column() {
Text(this.html.realtime.humidity || '--').textStyle()
}.weatherStyle().alignItems(HorizontalAlign.Start)
Column() {
Text(this.html.realtime.info || '--').textStyle()
}.weatherStyle().alignItems(HorizontalAlign.Start)
Column() {
Text(this.html.realtime.wid || '--').textStyle()
}.weatherStyle().alignItems(HorizontalAlign.Start)
Column() {
Text(this.html.realtime.direct || '--').textStyle()
}.weatherStyle().alignItems(HorizontalAlign.Start)
Column() {
Text(this.html.realtime.power || '--').textStyle()
}.weatherStyle().alignItems(HorizontalAlign.Start)
Column() {
Text(this.html.realtime.aqi || '--').textStyle()
}.weatherStyle().alignItems(HorizontalAlign.Start)
}
.width('100%')
.height('100%')
.padding(10)
}
private httpRequest() {
httpRequest(this.url).then(res => {
const data: resultType = res.data as resultType;
this.html = data.result;
console.info('网络结果:'+JSON.stringify(data));
});
}
}
5.2 泛型式
5.2.1 封装
import http from '@ohos.net.http';
// 1、创建RequestOption.ets 配置类
export interface RequestOptions {
url?: string;
method?: RequestMethod; // default is GET
queryParams ?: Record<string, string>;
extraData?: string | Object | ArrayBuffer;
header?: Object; // default is 'content-type': 'application/json'
}
export enum RequestMethod {
OPTIONS = "OPTIONS",
GET = "GET",
HEAD = "HEAD",
POST = "POST",
PUT = "PUT",
DELETE = "DELETE",
TRACE = "TRACE",
CONNECT = "CONNECT"
}
/**
* Http请求器
*/
export class HttpCore {
/**
* 发送请求
* @param requestOption
* @returns Promise
*/
request<T>(requestOption: RequestOptions): Promise<T> {
return new Promise<T>((resolve, reject) => {
this.sendRequest(requestOption)
.then((response) => {
if (typeof response.result !== 'string') {
reject(new Error('Invalid data type'));
} else {
let bean: T = JSON.parse(response.result);
if (bean) {
resolve(bean);
} else {
reject(new Error('Invalid data type,JSON to T failed'));
}
}
})
.catch((error) => {
reject(error);
});
});
}
private sendRequest(requestOption: RequestOptions): Promise<http.HttpResponse> {
// 每一个httpRequest对应一个HTTP请求任务,不可复用
let httpRequest = http.createHttp();
let resolveFunction, rejectFunction;
const resultPromise = new Promise<http.HttpResponse>((resolve, reject) => {
resolveFunction = resolve;
rejectFunction = reject;
});
if (!this.isValidUrl(requestOption.url)) {
return Promise.reject(new Error('url格式不合法.'));
}
let promise = httpRequest.request(this.appendQueryParams(requestOption.url, requestOption.queryParams), {
method: requestOption.method,
header: requestOption.header,
extraData: requestOption.extraData, // 当使用POST请求时此字段用于传递内容
expectDataType: http.HttpDataType.STRING // 可选,指定返回数据的类型
});
promise.then((response) => {
console.info('Result:' + response.result);
console.info('code:' + response.responseCode);
console.info('header:' + JSON.stringify(response.header));
if (http.ResponseCode.OK !== response.responseCode) {
throw new Error('http responseCode !=200');
}
resolveFunction(response);
}).catch((err) => {
rejectFunction(err);
}).finally(() => {
// 当该请求使用完毕时,调用destroy方法主动销毁。
httpRequest.destroy();
})
return resultPromise;
}
private appendQueryParams(url: string, queryParams: Record<string, string>): string {
// todo 使用将参数拼接到url上
return url;
}
private isValidUrl(url: string): boolean {
//todo 实现URL格式判断
return true;
}
}
// 实例化请求器
const httpCore = new HttpCore();
export class HttpManager {
private static mInstance: HttpManager;
// 防止实例化
private constructor() {
}
static getInstance(): HttpManager {
if (!HttpManager.mInstance) {
HttpManager.mInstance = new HttpManager();
}
return HttpManager.mInstance;
}
request<T>(option: RequestOptions): Promise<T> {
return httpCore.request(option);
}
}
export default HttpManager;
5.2.2 使用
import httpManager, { RequestMethod } from '../../utils/requestManager';
interface TestBean {
userId: number,
id: number,
title: string,
completed: boolean
}
private handleClick() {
httpManager.getInstance()
.request<TestBean>({
method: RequestMethod.GET,
url: 'https://jsonplaceholder.typicode.com/todos/1' //公开的API
})
.then((result) => {
this.text = JSON.stringify(result);
console.info(JSON.stringify(result));
})
.catch((err) => {
console.error(JSON.stringify(err));
});
}