如何用async/await处理同函数内嵌套fetch调用的返回值异常问题
问题诱因
- 数组
map回调的async函数没有返回值:你在map的异步回调里只做了赋值操作input = await {...input, ...foo},但没有把合并后的对象return出来,所以每个Promise最终fulfilled的结果都是undefined,这是你拿到全undefined数组的核心原因。 - 直接对Promise数组使用
await无效:await只能处理单个Promise实例,store.map(async ()=>{})返回的是一个由Promise组成的普通数组,直接await这个数组不会等待所有异步任务执行完成,必须用Promise.all()包裹后再await。 - 单个请求异常未捕获:控制台里第4个Promise rejected是因为对应
${input.id}.json的接口返回了非JSON格式内容(大概率是404/500错误页的HTML代码,以<开头),没有做异常捕获会导致整个Promise.all直接失败。 - 多余的await操作:对象展开
{...input, ...foo}是同步运算,不需要加await,不会影响运行但属于冗余代码。
修复方案
1. 修改getData函数
export default async function getData() { // 拆分异步逻辑,避免混用await和then增加理解成本 const dataUrl = await request('http://localhost:2000/api/ves.json'); const response = await fetch(dataUrl); const store = await response.json(); // 给每个异步请求加异常捕获,避免单个请求失败拖垮整个列表 const promiseList = store.map(async (input) => { try { const detailUrl = await request(`http://localhost:2000/api/${input.id}.json`); const detailRes = await fetch(detailUrl); const foo = await detailRes.json(); // 必须return合并后的对象,Promise的返回值才会是你要的结果 return {...input, ...foo}; } catch (err) { // 单个请求失败时可以返回原input,或者自定义错误标记,根据业务需求调整 console.error(`id为${input.id}的请求失败:`, err); return input; } }); // 等待所有异步任务执行完成,返回结果数组 return await Promise.all(promiseList); }
2. 修改React侧调用逻辑
异步函数返回的始终是Promise实例,不能直接解构拿到请求结果,需要在自定义Hook内部用state存储返回值,示例如下:
// 自定义useData Hook示例 function useData() { const [ves, setVes] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { const fetchData = async () => { const data = await getData(); setVes(data); setLoading(false); }; fetchData(); }, []); return [ves, loading]; } // 组件内调用 const [ves, loading] = useData(); useEffect(() => { if (!loading) { console.log(ves); // 此处可拿到合并完成的目标数组 } }, [ves, loading]);
内容的提问来源于stack exchange,提问作者Alexander Hemming
相关产品推荐
相关产品推荐

