JS使用fetch调用Laravel API时如何处理错误并在表单展示
如何正确获取响应中的错误JSON
fetch的默认规则是仅当网络层面请求失败(如断网、跨域被拦截、DNS解析失败)时才会触发catch回调,400、422、500等HTTP业务状态码都会正常进入then回调,所以你把错误解析逻辑写在catch里本身就无法拿到正常的接口响应。
同时response.json()是异步方法,返回Promise对象,必须通过await或者.then()才能拿到解析完成的JSON数据。
正确的请求写法参考:
const form = document.getElementById('commentForm'); form.addEventListener('submit', async (e) => { e.preventDefault(); // 先清空上一次提交的错误提示 document.querySelectorAll('.form-error-tip').forEach(el => el.remove()); const formData = new FormData(form); try { const response = await fetch('/api/comments', { method: 'POST', body: formData }); // 状态码非2xx时处理业务错误 if (!response.ok) { const errorJson = await response.json(); // 这里已经拿到结构为{字段名:[错误提示]}的错误对象 renderErrors(errorJson); return; } // 成功提交的后续逻辑 const result = await response.json(); alert('评论提交成功'); } catch (networkError) { // 这里仅处理网络异常 alert('网络连接失败,请检查网络后重试'); } })
结合FormData批量展示表单错误的优化方案
因为FormData的字段name属性和Laravel校验返回的错误字段名完全对应,完全可以做通用的错误渲染逻辑,不需要每个字段单独处理:
function renderErrors(errors) { // 遍历所有错误字段 Object.entries(errors).forEach(([fieldName, errorMessages]) => { // 根据name属性匹配对应表单字段 const targetField = document.querySelector(`[name="${fieldName}"]`); if (!targetField) return; // 生成错误提示元素插入到字段下方 const errorTip = document.createElement('p'); errorTip.className = 'form-error-tip text-red-500 text-xs mt-1'; // 取第一条错误展示,如需展示所有错误可遍历errorMessages拼接 errorTip.innerText = errorMessages[0]; targetField.parentNode.insertBefore(errorTip, targetField.nextSibling); // 可选:给表单字段加错误样式 targetField.classList.add('border', 'border-red-500'); // 可选:字段聚焦时自动清除错误提示和样式 targetField.addEventListener('focus', () => { errorTip.remove(); targetField.classList.remove('border-red-500'); }, { once: true }) }) }
如果涉及嵌套校验的字段(比如Laravel校验规则写的user.email),只需要把对应表单字段的name属性也设置为user.email即可,无需修改通用渲染逻辑。
内容的提问来源于stack exchange,提问作者Maik Lowrey
相关产品推荐
相关产品推荐

