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

12 回复

你的拦截器这里判断url有缓存直接返回了,如果你不需要拦截器,可以不传interceptors参数,或者把缓存判断这里修改或注释掉

cke_149.png

更多关于HarmonyOS 鸿蒙Next中rcp同一个请求直接返回上一次请求结果的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


咱俩看法一致,


相关图片未提供,因此无图片插入。

大佬正解,感谢,

有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html

我慢了一步啊!

cke_140.png

你这拦截器不是有缓存吗?如果请求路径一样了 就取的缓存的数据啊

可能是缓存。。。你最好加上代理抓一下包看看到底服务器返回的内容

用的模拟器,也不知道是否是这个原因,

还有一点需要注意的是,同一个网络请求除了第一次能走拦截器打印log,后续的请求都不会走拦截器。

被你的拦截器拦截了啊 直接return了 后续的日志也就看不到了,

在鸿蒙Next中,rcp请求返回上一次结果可能是由于缓存机制导致的。鸿蒙的分布式能力框架为了提高性能,可能会缓存某些请求的响应数据。这属于预期行为,特别是在网络状况不佳或重复请求相同资源时。

要解决这个问题,可以在发起rcp请求时设置不缓存标志,或者使用新的请求ID避免重复。具体可通过修改RPC调用的options参数,将缓存策略设置为NO_CACHE。

如果是持续性服务调用,建议检查服务端的实现逻辑,确保每次请求都能生成新的响应数据。

从代码来看,这个问题是由于在RcpInterceptor拦截器中实现了请求缓存逻辑导致的。关键点在于:

  1. ResponseCache类中,使用了一个简单的对象缓存所有请求响应。
  2. 拦截器在intercept方法中会先检查缓存,如果存在就直接返回缓存的响应。
  3. 每次请求成功后都会将响应存入缓存。

解决方案建议:

  1. 移除ResponseCache缓存逻辑,或者添加缓存过期机制。
  2. 对于需要缓存的请求,可以单独处理而不是全局缓存。
  3. 检查是否真的需要缓存所有请求,通常只有GET请求适合缓存。

修改建议:

  1. 删除RcpInterceptor中的缓存逻辑。
  2. 或者在缓存前检查请求方法,只缓存GET请求。
  3. 或者添加缓存时间戳,实现缓存过期。

当前实现会导致所有相同URL的请求都返回第一次的响应结果,这显然不是期望的行为。

回到顶部