在React useEffect中使用map结合Axios为何返回Promise数组而非目标对象数组?
问题原因分析
你遇到的这个问题其实很常见:因为async函数本身的返回值就是一个Promise,当你把async function作为map的回调函数时,map遍历后得到的数组里每个元素都是Promise实例,而不是你期望的处理后的资产对象——这就是控制台打印出一堆Promise的核心原因。
解决方案
要解决这个问题,你需要用Promise.all()来等待所有异步请求完成,拿到真正的结果数组后再更新状态。另外要注意:useEffect的回调函数不能直接设为async,所以我们可以在它内部定义一个异步函数并调用。
修改后的代码如下:
useEffect(() => { // 定义内部异步函数,处理所有资产请求逻辑 const fetchAndProcessAssets = async () => { // 用Promise.all等待所有异步请求完成,拿到最终的结果数组 const newAssetArray = await Promise.all( dummyAssets.map(async (asset) => { try { const response = await axios.get(currrentPrice(asset.asset_id)); const cp = response.data.market_data.current_price.eur; const value = Number(cp) * Number(asset.amount); // 返回添加了value字段的新资产对象 return { ...asset, value: +value }; } catch (error) { console.log(error.response.data.error); // 这里可以自定义请求失败时的返回值,比如标记错误状态或保留原资产 return { ...asset, value: null, hasError: true }; } }) ); setAssets(newAssetArray); console.log(newAssetArray); }; // 调用内部异步函数 fetchAndProcessAssets(); }, [dummyAssets]);
关键改动说明
- 用
Promise.all()包裹map的结果,通过await等待所有请求完成,就能得到包含处理后对象的真实数组 - 将异步逻辑封装在内部函数中,避免直接把
useEffect回调设为async(这会导致React无法正确清理副作用) - 把原来的
.then/.catch换成try/catch写法,逻辑更直观,还能在请求失败时统一处理返回值(比如给失败的资产标记错误状态)
如果想过滤掉请求失败的资产,可以在Promise.all之后加一步处理:
const validAssets = newAssetArray.filter(item => !item.hasError); setAssets(validAssets);
内容的提问来源于stack exchange,提问作者Clancinio
相关产品推荐
相关产品推荐

