Next.js中getServerSideProps内能否按顺序执行两次存在依赖的API调用?
问题1:getServerSideProps存在未定义变量
你在返回的props里直接写了movieId: movieId,但整个getServerSideProps作用域里根本没有定义movieId这个变量,这是直接触发运行时错误的核心原因,也是导致ChunkLoadError的诱因之一。
修复:要么删除这个无用的prop,要么如果确实需要传movieId,就从event.externalData.movieId取值。
问题2:movie为空时页面直接报错
当event没有externalData字段,或者getMovieById请求失败时,movieProp的值是null/错误对象,你在页面中直接写{movie.originalTitle}会直接触发空指针错误。
修复:在渲染movie字段时加可选链或者非空判断,比如改成{movie?.originalTitle},或者先判断movie是否存在再渲染对应的标签。
问题3:getMovieById请求异常的原因
- 你全局配置的
companyClient里固定加了data: formData,所有post请求都会默认携带这个提前定义的formData,可能会导致目标接口参数解析错误,返回异常内容。 - 全局配置的timeout只有3000ms,如果接口响应超过3秒就会直接触发超时,你看到的超时日志就是这个参数导致的,可以根据实际情况调大超时时间。
getMovieById的catch分支直接返回error对象,没有做降级处理,你拿到的movie可能是个错误对象,根本不存在originalTitle字段。
修复:
- 移除companyClient里全局的
data: formData配置,改成需要传formData的请求单独在请求里传。 - 把timeout调大到合理范围,比如10000(10秒)。
- 给getMovieById加降级返回,catch的时候返回null或者空对象,避免返回错误对象。
问题4:ChunkLoadError的处理
先把上面的所有运行时错误修复后,删除项目根目录下的.next文件夹,重启开发服务即可,这个错误本质是你代码里有未捕获的运行时错误,导致Next.js编译的缓存chunk损坏导致的。
修改后代码示例
getServerSideProps代码
export async function getServerSideProps(context) { const venueId = context.params.venueId; const date = context.params.slug[0]; const eventId = context.params.slug[1]; const locale = context.locale; const event = await getEventTypeByVenueIdAndDate(venueId, date, eventId); const eventAsJson = JSON.parse(JSON.stringify(event)) let movie = null let movieId = null if (event?.externalData?.movieId) { movieId = event.externalData.movieId movie = await getMovieById(movieId); console.log('ServerSide movie-data:', movie); } return { props: { venueId: venueId, movieId: movieId, date: date, eventProp: eventAsJson, eventId: eventId, locale: locale, movieProp: movie ? JSON.parse(JSON.stringify(movie)) : null, }, }; }
页面代码
export default function EventDetailPage(props) { const { eventProp, movieId, date, eventId, locale, movieProp, cineamoId } = props const [event, setEvent] = useState(eventProp); const [movie, setMovie] = useState(movieProp); if (!event) { return ( <> <LoadingAnimation/> </> ); } return(<div> <h1>{event.name}</h1> <h1>{movie?.originalTitle}</h1> </div> ) }
getMovieById函数代码
import { companyClient } from "./apiClient" export async function getMovieById(movieId){ let param = `movie/display/${movieId}`; return companyClient.post(param) .then(response => { console.log(response.data.items[0]); return response.data.items?.[0] || null; }) .catch(function (error) { console.error('获取电影信息失败', error) return null; }); }
companyClient配置
export const companyClient = axios.create({ baseURL: process.env.NEXT_PUBLIC_ENV_LOCAL_VARIABLE, headers: headers, auth: { username: "************", password: "************" }, timeout: 10000, withCredentials: true, });
内容的提问来源于stack exchange,提问作者Simon Gowing
相关产品推荐
相关产品推荐

