HarmonyOS 鸿蒙Next中rcp同一个请求直接返回上一次请求结果
HarmonyOS 鸿蒙Next中rcp同一个请求直接返回上一次请求结果
import { CacheUtil, JSONUtil, KvUtil } from '@pura/harmony-utils'
import { rcp } from '@kit.RemoteCommunicationKit'
import { BASE_URL } from './NetUrl'
import { BusinessError } from '@kit.BasicServicesKit';
import { LogUtil } from '../utils/log/LogUtil';
import { LogTag } from '../utils/log/LogTag';
import { KvConstants } from '../data/Constans';
const CONNECT_TIME = 5000
const TRANSFER_TIME = 10000
const INACTIVITY_TIME = 10000
//拦截器
class ResponseCache {
private readonly cache: Record<string, rcp.Response> = {};
getResponse(url: string): rcp.Response {
return this.cache[url];
}
setResponse(url: string, response: rcp.Response): void {
this.cache[url] = response;
}
}
class RcpInterceptor implements rcp.Interceptor {
private readonly cache: ResponseCache;
constructor(cache: ResponseCache) {
this.cache = cache;
}
async intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {
const url = context.request.url.href;
const responseFromCache = this.cache.getResponse(url);
if (responseFromCache) {
return Promise.resolve(responseFromCache);
}
try {
//获取当前请求url
LogUtil.d(LogTag.NET,`========================网络请求开始========================`)
LogUtil.d(LogTag.NET,`URL:${context.request.url.href}` )
LogUtil.d(LogTag.NET,`type:${context.request.method}`)
if (context.request.headers) {
context.request.headers["Authorization"] = await KvUtil.getString(KvConstants.TOKEN,"")
LogUtil.d(LogTag.NET,`header:${JSONUtil.beanToJsonStr(context.request.headers as object)}`
}
if (context.request.cookies) {
LogUtil.d(LogTag.NET,`cookie:${JSONUtil.beanToJsonStr(context.request.cookies as object)}`
}
if (context.request.content) {
LogUtil.d(LogTag.NET,`data:${JSONUtil.beanToJsonStr(context.request.content)}`
}
LogUtil.d(LogTag.NET,`========================网络请求开始========================`)
} catch (error) {
//抛出
return Promise.reject(error);
}
const promise = next.handle(context);
promise.then((resp) => {
LogUtil.d(LogTag.NET,`========================网络请求结束========================`)
LogUtil.d(LogTag.NET,`响应状态:${resp.statusCode}`
LogUtil.d(LogTag.NET,`响应内容:${resp.toString() as string}`
LogUtil.d(LogTag.NET,`========================网络请求结束========================`)
this.cache.setResponse(url, resp);
});
return promise;
}
}
//rcp请求配置
const cache = new ResponseCache()
export let sessionConfig:rcp.SessionConfiguration = {
requestConfiguration: {
transfer: {
autoRedirect: true,
timeout: {
//允许建立连接的最长时间
connectMs: CONNECT_TIME,
//允许传输数据的最长时间
transferMs: TRANSFER_TIME,
//网络传输持续进行,但是服务端收到数据或者客户端收到数据的时间间隔比较长,超出了预期,
//那么请求会异常。也就是说应用觉得网速太慢用户体验不好的时候,请求取消,执行异常分支
inactivityMs:INACTIVITY_TIME
}
}
},
baseAddress:BASE_URL,
headers:{
'Content-Type': 'application/json'
},
interceptors:[new RcpInterceptor(cache)]
}
//创建rcp
export class BaseRcp{
/**
* 封装后的全局rcp对象
*/
private session: rcp.Session | undefined;
/**
* 私有化构造
*/
private constructor() {
}
/**
* 私有单例对象
*/
private static rcpInstance: BaseRcp;
/**
* 创建单例
* @returns
*/
public static getInstance(): BaseRcp {
if (!BaseRcp.rcpInstance) {
BaseRcp.rcpInstance = new BaseRcp();
}
return BaseRcp.rcpInstance;
}
/**
* 创建session对象
* @returns
*/
create(): BaseRcp {
if (this.session) {
this.session.close();
this.session = undefined;
}
this.session = rcp.createSession(sessionConfig);
return this;
}
/**
* 构建efRcpSession对象
* @returns
*/
builder(): rcp.Session {
if (this.session === undefined) {
throw new Error("构建RcpSession异常,请在构建之前调用create方法创建")
}
return this.session as rcp.Session;
}
}
//返回的数据基本数据类型
export interface BaseResponse<T> {
code: number;
msg: string;
data: T;
}
//返回的数据异形数据类型
export interface BaseExtResponse<T> {
code: number;
msg: string;
rows: T;
}
//业务成功的code
export const CODE_SUCCESS = 200
更多关于HarmonyOS 鸿蒙Next中rcp同一个请求直接返回上一次请求结果的实战教程也可以访问 https://www.itying.com/category-93-b0.html
你的拦截器这里判断url有缓存直接返回了,如果你不需要拦截器,可以不传interceptors参数,或者把缓存判断这里修改或注释掉
更多关于HarmonyOS 鸿蒙Next中rcp同一个请求直接返回上一次请求结果的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
咱俩看法一致,
相关图片未提供,因此无图片插入。
大佬正解,感谢,
有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html
我慢了一步啊!
你这拦截器不是有缓存吗?如果请求路径一样了 就取的缓存的数据啊
可能是缓存。。。你最好加上代理抓一下包看看到底服务器返回的内容
用的模拟器,也不知道是否是这个原因,
还有一点需要注意的是,同一个网络请求除了第一次能走拦截器打印log,后续的请求都不会走拦截器。
被你的拦截器拦截了啊 直接return了 后续的日志也就看不到了,
在鸿蒙Next中,rcp请求返回上一次结果可能是由于缓存机制导致的。鸿蒙的分布式能力框架为了提高性能,可能会缓存某些请求的响应数据。这属于预期行为,特别是在网络状况不佳或重复请求相同资源时。
要解决这个问题,可以在发起rcp请求时设置不缓存标志,或者使用新的请求ID避免重复。具体可通过修改RPC调用的options参数,将缓存策略设置为NO_CACHE。
如果是持续性服务调用,建议检查服务端的实现逻辑,确保每次请求都能生成新的响应数据。
从代码来看,这个问题是由于在RcpInterceptor
拦截器中实现了请求缓存逻辑导致的。关键点在于:
- 在
ResponseCache
类中,使用了一个简单的对象缓存所有请求响应。 - 拦截器在
intercept
方法中会先检查缓存,如果存在就直接返回缓存的响应。 - 每次请求成功后都会将响应存入缓存。
解决方案建议:
- 移除
ResponseCache
缓存逻辑,或者添加缓存过期机制。 - 对于需要缓存的请求,可以单独处理而不是全局缓存。
- 检查是否真的需要缓存所有请求,通常只有GET请求适合缓存。
修改建议:
- 删除
RcpInterceptor
中的缓存逻辑。 - 或者在缓存前检查请求方法,只缓存GET请求。
- 或者添加缓存时间戳,实现缓存过期。
当前实现会导致所有相同URL的请求都返回第一次的响应结果,这显然不是期望的行为。