Nuxt中AsyncData发起多个axios请求报错404/500问题求助
问题核心原因
- 你的业务属于互斥场景:从模板的
v-if="blogPost"和v-else-if="blogCategoryPosts"逻辑可以看出,同一个路由路径下,两个接口必然只有一个会返回正常数据,另一个会返回404/500。你当前的写法没有做错误捕获,只要任意一个请求报错,就会直接终止asyncData执行,抛出全局错误。 Promise.all的特性是只要传入的Promise实例有一个变为rejected状态,就会直接返回rejected结果,不会等待其他请求完成,所以只要其中一个接口报错,整个请求逻辑就会失败。- 串行await的写法同理,没有加错误捕获的话,前一个请求报错就会直接抛出错误,不会执行后续代码。
解决方案
方案1:使用Promise.allSettled兼容成功/失败状态
适配你的互斥场景,不管接口成功失败都会返回结果,你自行筛选出成功的接口数据使用即可:
<template> <div v-if="blogPost"> <p>post</p> </div> <div v-else-if="blogCategoryPosts"> <p>category,posts</p> </div> </template> <script> export default { async asyncData({ $axios, app, route}) { const [postRes, categoryRes] = await Promise.allSettled([ $axios.get(`${process.env.API_DOMAIN}/api/blog/posts${route.path}`), $axios.get(`${process.env.API_DOMAIN}/api/blog/categories${route.path}`), ]) return { blogPost: postRes.status === 'fulfilled' ? postRes.value.data : null, blogCategoryPosts: categoryRes.status === 'fulfilled' ? categoryRes.value.data : null, } }, } </script>
方案2:串行请求单独加try/catch捕获错误
如果不想同时发起两个请求,可以用单个捕获错误的方式依次尝试:
async asyncData({ $axios, app, route }) { let blogPost = null let blogCategoryPosts = null try { const postRes = await $axios.get(`${process.env.API_DOMAIN}/api/blog/posts${route.path}`) blogPost = postRes.data } catch (e) { // 文章接口请求失败,尝试请求分类接口 try { const categoryRes = await $axios.get(`${process.env.API_DOMAIN}/api/blog/categories${route.path}`) blogCategoryPosts = categoryRes.data } catch (err) { // 两个接口都失败时可在此处处理全局404逻辑 } } return { blogPost, blogCategoryPosts } }
方案3(更推荐):提前判断路由类型,只发必要请求
如果你的路由规则可以区分页面类型(比如文章路径是/blog/posts/xxx,分类路径是/blog/categories/xxx),最好提前判断路由类型,只发起对应请求,避免无效请求浪费资源:
async asyncData({ $axios, route }) { let blogPost = null let blogCategoryPosts = null // 此处可替换为你的实际路由判断规则 if (route.path.startsWith('/blog/posts/')) { const res = await $axios.get(`${process.env.API_DOMAIN}/api/blog/posts${route.path}`) blogPost = res.data } else if (route.path.startsWith('/blog/categories/')) { const res = await $axios.get(`${process.env.API_DOMAIN}/api/blog/categories${route.path}`) blogCategoryPosts = res.data } return { blogPost, blogCategoryPosts } }
内容的提问来源于stack exchange,提问作者RedEclipse
相关产品推荐
相关产品推荐

