uniCloud云对象并行请求遇到未鉴权时promise状态无法落定

uniCloud云对象并行请求遇到未鉴权时promise状态无法落定

产品分类:uniCloud/App

示例代码:

try {  
    await Promise.all([  
     // 这5个请求都是通过uniCloud云对象发出  
      guestStore.fetchGuests(),  
      eventStore.readEventsByUserId(),  
      ledgerStore.readLedgersByUserId(),  
      recordStore.readRecordsByUserId(),  
      cashGiftStore.fetchCashGifts(),  
    ]);  

    console.log("初始化数据成功");  

    isInitialized.value = true;  
} catch (error: any) {  
    console.error("初始化数据失败", error);  
    initializationError.value = `Failed to initialize stores: ${error.message}`;  
} finally {  
    isInitializing.value = false;  
}

操作步骤:

程序会在onLaunch时初始化应用数据,然后更改全局状态
但由于请求被挂起,导致无法执行await后面的代码以及catch和finally代码都不会被执行

预期结果:

并行请求时正确处理Promise落定状态
PS: 这些模块是否有能够开源出来,发动社区的力量一起维护

实际结果:

未处理

bug描述:

利用Promise.all同时发起5请求,这5个请求都是通过云对象方式进行调用,都需要鉴权
如果某个请求遇到鉴权失败的情况下,会自动弹框提示并且当前请求的Promise进入catch状态
但另外4个请求就一直处于挂起状态


5 回复

但另外4个请求就一直处于挂起状态,你是怎么确定的,从浏览器网络请求看的吗,发下截图


另外4个请求已经完成,并且已经执行了uni.showMdal函数

但是这四个请求的Promise还是pendding状态,既没有被reject,也没有被resolve.

因为没有执行finally函数

这是一个典型的Promise.all并发请求问题。当Promise.all中任意一个Promise被reject时,整个Promise.all会立即reject,但其他仍在pending状态的Promise不会被取消,它们会继续挂起等待响应。

在uniCloud云对象场景下,鉴权失败会导致对应的Promise进入reject状态,触发Promise.all的catch,但其他请求由于服务端仍在处理或等待响应,客户端无法主动取消这些pending的Promise。

解决方案:

  1. 使用Promise.allSettled替代Promise.all
const results = await Promise.allSettled([
  guestStore.fetchGuests(),
  eventStore.readEventsByUserId(), 
  ledgerStore.readLedgersByUserId(),
  recordStore.readRecordsByUserId(),
  cashGiftStore.fetchCashGifts()
]);

const successfulResults = results.filter(result => result.status === 'fulfilled');
const failedResults = results.filter(result => result.status === 'rejected');

console.log("初始化完成", successfulResults.length, "个成功", failedResults.length, "个失败");
  1. 为每个请求添加超时控制
const withTimeout = (promise, timeout = 10000) => {
  return Promise.race([
    promise,
    new Promise((_, reject) => 
      setTimeout(() => reject(new Error('请求超时')), timeout)
    )
  ]);
};
  1. 单独处理每个请求的异常
const requests = [
  guestStore.fetchGuests().catch(handleError),
  eventStore.readEventsByUserId().catch(handleError),
  // ... 其他请求
];

await Promise.all(requests);
回到顶部