Next.js电商网站/api/orders接口报错求助
电商网站接口报错排查(Next.js + Material-UI + Sanity)
我用Next.js开发电商网站,搭配Material-UI和Sanity,现在遇到接口报错,信息如下:
error: API resolved without sending a response for /api/orders, this may result in stalled requests
API handler should not return a value, received function.
怀疑问题出在placeOrderHandler函数,相关代码如下:
前端组件代码
function PlaceOrderScreen() { const { enqueueSnackbar } = useSnackbar(); const [loading, setLoading] = useState(false); const router = useRouter(); const { state, dispatch } = useContext(Store); const { userInfo, cart: { cartItems, shippingAddress, paymentMethod }, } = state; const round2 = (num) => Math.round(num * 100 + Number.EPSILON) / 100; // 123.456 => 123.46 const itemsPrice = round2( cartItems.reduce((a, c) => a + c.price * c.quantity, 0) ); const shippingPrice = itemsPrice > 100 ? 0 : 20; const taxPrice = round2(itemsPrice * 0.15); const totalPrice = round2(itemsPrice + shippingPrice + taxPrice); useEffect(() => { if (!paymentMethod) { router.push('/payment'); } if (cartItems.length === 0) { router.push('/cart'); } }, [cartItems, paymentMethod, router]); const placeOrderHandler = async () => { try { setLoading(true); const { data } = await axios.post( '/api/orders', { orderItems: cartItems.map((x) => ({ ...x, countInStock: undefined, slug: undefined, })), shippingAddress, paymentMethod, itemsPrice, shippingPrice, taxPrice, totalPrice, }, { headers: { authorization: `Bearer ${userInfo.token}`, }, } ); dispatch({ type: 'CART_CLEAR' }); jsCookie.remove('cartItems'); setLoading(false); router.push(`/order/${data}`); } catch (err) { setLoading(false); enqueueSnackbar(getError(err), { variant: 'error' }); } }; return ( <Layout title="Place Order"> <CheckoutWizard activeStep={3}></CheckoutWizard> <Typography component="h1" variant="h1"> Place Order </Typography> <Grid item md={3} xs={12}> <Card sx={classes.section}> <List> <ListItem> <Typography variant="h2">Order Summary</Typography> </ListItem> <ListItem> <Grid container> <Grid item xs={6}> <Typography>Items:</Typography> </Grid> <Grid item xs={6}> <Typography align="right">${itemsPrice}</Typography> </Grid> </Grid> </ListItem> <ListItem> <Grid container> <Grid item xs={6}> <Typography>Shipping:</Typography> </Grid> <Grid item xs={6}> <Typography align="right">${shippingPrice}</Typography> </Grid> </Grid> </ListItem> <ListItem> <Grid container> <Grid item xs={6}> <Typography> <strong>Total:</strong> </Typography> </Grid> <Grid item xs={6}> <Typography align="right"> <strong>${totalPrice}</strong> </Typography> </Grid> </Grid> </ListItem> <ListItem> <Button onClick={placeOrderHandler} variant="contained" color="primary" fullWidth disabled={loading} > Place Order </Button> </ListItem> {loading && ( <ListItem> <CircularProgress /> </ListItem> )} </List> </Card> </Grid> </Layout> ); } export default dynamic(() => Promise.resolve(PlaceOrderScreen), { ssr: false });
API处理器代码
import axios from 'axios'; import { isAuth } from '../../../utils/auth'; import config from '../../../utils/config'; import { createRouter } from 'next-connect'; const router = createRouter(); router.use(isAuth); router.post(async (req, res) => { const projectId = config.projectId; const dataset = config.dataset; const tokenWithWriteAccess = process.env.SANITY_AUTH_TOKEN; const { data } = await axios.post( `https://${projectId}.api.sanity.io/v1/data/mutate/${dataset}?returnIds=true`, { mutations: [ { create: { _type: 'order', createdAt: new Date().toISOString(), ...req.body, userName: req.user.name, user: { _type: 'reference', _ref: req.user._id, }, }, }, ], }, { headers: { 'Content-type': 'application/json', Authorization: `Bearer ${tokenWithWriteAccess}`, }, } ); res.status(201).send(data.results[0].id); }); export default router.handler;
问题分析与修复方案
这两个报错的核心问题集中在API路由的响应处理逻辑上:
1. API handler should not return a value, received function 报错原因
Next.js API路由要求处理器要么发送响应,要么调用next()传递流程,不能返回函数。问题大概率出在isAuth中间件上:
- 如果
isAuth验证失败时没有直接发送响应(比如res.status(401).json(...)),而是返回了函数或者没有终止流程,就会触发这个错误。
修复isAuth中间件:
确保验证失败时立即发送响应并终止流程,验证通过才调用next()传递到后续处理:
export const isAuth = async (req, res, next) => { const authorization = req.headers.authorization; if (!authorization || !authorization.startsWith('Bearer ')) { return res.status(401).json({ message: '未提供有效令牌' }); } // 解析令牌并验证用户逻辑... const token = authorization.split(' ')[1]; try { // 你的验证逻辑,比如解码JWT获取用户信息 const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = decoded; next(); // 验证通过才继续执行后续路由 } catch (err) { return res.status(401).json({ message: '令牌无效' }); } };
2. API resolved without sending a response 报错原因
这个错误说明请求进入API路由后,没有任何响应被发送,可能的场景:
isAuth中间件未处理异常,导致请求卡在中间件流程中post处理函数中的异步操作出错,但没有捕获错误并返回响应
修复API路由的post处理函数:
添加错误捕获逻辑,确保任何异常都能返回响应:
router.post(async (req, res) => { try { const projectId = config.projectId; const dataset = config.dataset; const tokenWithWriteAccess = process.env.SANITY_AUTH_TOKEN; const { data } = await axios.post( `https://${projectId}.api.sanity.io/v1/data/mutate/${dataset}?returnIds=true`, { mutations: [ { create: { _type: 'order', createdAt: new Date().toISOString(), ...req.body, userName: req.user.name, user: { _type: 'reference', _ref: req.user._id, }, }, }, ], }, { headers: { 'Content-type': 'application/json', Authorization: `Bearer ${tokenWithWriteAccess}`, }, } ); res.status(201).send(data.results[0].id); } catch (err) { // 捕获所有异常并返回错误响应 res.status(500).json({ message: err.message || '创建订单失败' }); } });
3. 验证路由导出方式
如果使用的是Next.js Pages Router,确保正确调用handler()方法导出:
export default router.handler(); // 注意要调用handler方法,而不是直接导出handler属性
内容的提问来源于stack exchange,提问作者Naveer
相关产品推荐
相关产品推荐

