HarmonyOS 线程锁在arkts有对应的替代方案吗?

HarmonyOS 线程锁在arkts有对应的替代方案吗?

在接口响应中处理401状态码,因此需要用到synchronized这种线程同步锁,请问ArkTS有对应解决方案吗?
场景:
1、如果我异步请求10个后端接口,所有接口都返回401。
2、此时我需要在第一个返回的“响应1”中刷新token(加锁,避免其他9个接口响应后都去刷新)。
3、“响应1”释放锁后,其他9个响应依次获取锁,判断已经刷新token,则重新发起请求。如何实现?

阅读 798
avatarAI BotBETA

在HarmonyOS的ArkTS(ArkUI的TypeScript版本)环境中,由于ArkTS主要用于UI层面的开发,并不直接处理多线程同步问题(如Java或Kotlin中的synchronized关键字),因为它运行在单线程的UI框架中。然而,对于涉及到网络请求的场景,如你描述的异步请求并处理401状态码,通常不需要在ArkTS层面直接处理线程锁。

针对你的需求,你可以使用JavaScript或TypeScript的异步特性和状态管理来解决这个问题,而不是依赖传统的线程锁机制。以下是一个可能的解决方案:

  1. 状态管理:在ArkTS的页面中,使用全局状态或组件状态来管理token的状态和是否需要刷新的逻辑。
  2. 异步请求队列:对于所有需要发送的请求,可以使用一个队列(如使用数组)来管理。当第一个请求返回401时,触发token刷新逻辑,并暂停队列中其他请求的发送。
  3. Promise 或 async/await:使用Promise或async/await来处理异步请求,这样可以更优雅地处理请求的顺序和结果。
  4. 事件监听:当token刷新完成后,可以触发一个事件或回调函数,通知队列中的其他请求重新发送。

下面是一个简化的示例代码框架:

// 假设有一个全局的token和token刷新状态
let accessToken = 'initialToken';
let isRefreshingToken = false;

// 发送请求的函数,包含token刷新的逻辑
async function sendRequest(url: string): Promise<any> {
    try {
        const response = await fetch(url, {
            headers: {
                'Authorization': `Bearer ${accessToken}`
            }
        });

        if (response.status === 401) {
            if (!isRefreshingToken) {
                isRefreshingToken = true;
                accessToken = await refreshToken(); // 假设refreshToken会返回新的token并处理刷新逻辑
                isRefreshingToken = false;

                // 可以在这里重新发送队列中的请求,或者通知它们重新尝试
                // ...
            }
            // 可以选择重试请求或返回错误
            throw new Error('Unauthorized, token refreshed, retry needed');
        }

        return response.json();
    } catch (error) {
        console.error('Request failed:', error);
        throw error;
    }
}

// 刷新token的函数
async function refreshToken(): Promise<string> {
    // 模拟token刷新逻辑
    return new Promise(resolve => {
        setTimeout(() => {
            resolve('newAccessToken');
        }, 1000);
    });
}

// 调用示例
async function fetchData() {
    const urls = ['url1', 'url2', 'url3']; // 假设有10个这样的URL

    for (const url of urls) {
        try {
            const data = await sendRequest(url);
            console.log(data);
        } catch (error) {
            console.error('Failed to fetch data:', error);
        }
    }
}

fetchData();

注意:这个示例没有直接实现请求队列和重试逻辑,这通常需要根据你的具体应用场景来设计和实现。例如,你可以使用一个数组来存储待处理的请求,当token刷新后,遍历这个数组并重新发送请求。

总之,在ArkTS中处理这类问题,主要依赖于JavaScript/TypeScript的异步特性和状态管理,而不是传统的线程锁机制。

1 个回答

目前的并发模式不需要额外加锁 ArkTS语言基础类库提供的taskPool和worker两个多线程的方案,都是基于Actor并发模型实现的。Actor并发模型是基于事件基础传递数据,不需要开发者去面对锁代来的一系列复杂偶发的问题,是线程安全的,同时并发度也相对较高。目前线程间的数据传输支持的对象分为三类,普通的JavaScript对象,可转移对象,可共享对象。
有两个实现方案:1.可以尝试使用响应拦截器来处理,当前响应返回401时,去调用刷新token的接口,同时添加一个标记位判断token接口是否响应,在结果未响应,无法继续调用刷新接口。 使用三方库 @ohos/axios文档:https://gitee.com/openharmony-sig/ohos_axios#%E6%8B%A6%E6%88%...
2.通过typescript控制函数重入,管控其在单线程下运行 如下示例建立一个任务池和loop,再管理这个loop不可多次启动。

interface TaskItem { 
  /** 
   保存任务入参 
   / 
   tag: string; 
   /* 
   任务promise的回调 
   */ 
  resolve: (data: string) => void; 
} 
/** 
 保存任务队列 
 / 
 const lists: Array<TaskItem> = []; 
 /* 
 looper是否被启动了 
 */ 
let isLooperRunning: boolean = false; 
/** 
 //myFun的代理,本身不执行myFun,只是将他放入loop队列里面 
 @param tag 标签 
 */ 
async function myFunWapper(tag: string): Promise<string> { 
  const prom = new Promise<string>(resolve => { 
    lists.push({ tag, resolve }); 
  }); 
  looper(); 
  return prom; 
} 
/** 
 looper 
 */ 
async function looper(): Promise<string> { 
  if (isLooperRunning) { 
    console.debug(‘looper is running.’); 
    return; 
  } 
  isLooperRunning = true; 
  let currentItem = lists.shift(); 
  while (currentItem !== undefined) { 
    currentItem.resolve(await myFun(currentItem.tag)); 
    currentItem = lists.shift(); 
  } 
  isLooperRunning = false; 
} 
//因为此时,任务均被保存在lists队列中,无论外界调用myFunWapper是何种方式,运行myfun()不会出现重入的情况,运行代码如下,主逻辑是同时调用的,没有任何等待。 
/** 
 主逻辑 
 */ 
async function main2(): Promise<void> { 
  myFunWapper(‘1’).then((data) => { 
    console.log(“收到t1:”, data); 
  }); 
  myFunWapper(‘2’).then((data) => { 
    console.log(“收到t1:”, data); 
  }); 
  myFunWapper(‘3’).then((data) => { 
    console.log(“收到t1:”, data); 
  }); 
}

目前已支持AsyncLock,参考文档:https://gitee.com/openharmony/docs/blob/master/zh-cn/applicat...

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题