如何在React Hook中聚合多个Promise的返回结果?
问题解决方法
问题根源
你当前代码的核心问题是异步操作未等待完成就同步返回结果:
api.get返回的是Promise实例,then回调属于异步微任务,会在当前同步代码执行完毕后才触发。你在循环结束后直接返回results数组时,所有接口请求都还没有返回响应,因此数组永远是空值。
如果你之前尝试async/await写法未生效,通常是仅修改了getAll内部逻辑,没有在调用getAll的位置添加await,且调用getAll的外层函数没有添加async标识导致的。
修正后的自定义Hook代码
function useMyHook() { const api = useApiService(); return { getAll, }; // 修改返回类型为Promise<MyType[]>,添加async标识 async function getAll(arr: number[]): Promise<MyType[]> { // 生成所有请求的Promise数组 const requestPromises = arr.map(u => api.get(u)); // 等待所有请求完成,拿到所有返回结果 const allResults = await Promise.all(requestPromises); // 合并数组并去重后返回 return [...new Set(allResults.flat())]; } }
组件内调用方式
function MyComponent() { // ... const myHook = useMyHook(); // 调用函数添加async标识 const handleUse = async () => { // ... const numbers = [1, 2, 3]; // 等待异步方法返回结果 const myTypes = await myHook.getAll(numbers); const count = myTypes.length; // 此时可拿到正确的结果长度 // ... }; }
可选优化点
- 如果需要容忍部分请求失败,不影响其他正常返回的结果,可以把
Promise.all替换为Promise.allSettled,再过滤出成功的请求结果:
async function getAll(arr: number[]): Promise<MyType[]> { const requestPromises = arr.map(u => api.get(u)); const allResults = await Promise.allSettled(requestPromises); const validResults = allResults .filter((item): item is PromiseFulfilledResult<MyType[]> => item.status === 'fulfilled') .map(item => item.value); return [...new Set(validResults.flat())]; }
- 如果需要在组件卸载时中断未完成的请求,可以结合
AbortController实现请求取消,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Heldenkrieger01
相关产品推荐
相关产品推荐

