Promise中then语句失效求助:表单提交后无输出且报错
问题:表单提交Promise异常,.then无输出、URL异常跳转
我在表单提交触发的函数里用了Promise。首次提交表单时控制台完全没输出,之后每次提交都会触发.catch返回错误信息,而且URL会从http://127.0.0.1:8000/变成http://127.0.0.1:8000/?。我怀疑是API请求路径变成了/?/emails而非/emails导致的问题?作为JavaScript新手,想知道为什么.then的控制台输出不生效,哪里操作错了?
现有代码
JavaScript代码
document.addEventListener('DOMContentLoaded', function () { ... // Submit email document.querySelector('#compose-form').addEventListener('submit', submitEmail) }); function submitEmail() { fetch('/emails', { method: 'POST', body: JSON.stringify({ recipients: 'person@example.com', subject: 'Hello', body: 'Hello, world!' }) }) .then(response => response.json()) .then(result => { // Print result console.log(result); // this does not work }) .catch(error => { console.log('Error: idk something happened', error); // the error message that is shown // the error parameter does not actually show anything either, just the string is shown on the console }); }
HTML代码
<form id="compose-form"> <div class="form-group"> From: <input disabled class="form-control" value="{{ request.user.email }}"> </div> <div class="form-group"> To: <input id="compose-recipients" class="form-control"> </div> <div class="form-group"> <input class="form-control" id="compose-subject" placeholder="Subject"> </div> <textarea class="form-control" id="compose-body" placeholder="Body"></textarea> <input type="submit" class="btn btn-primary" id="submit-new" /> </form>
问题分析与解决
核心问题1:表单默认提交行为未阻止
表单点击提交按钮后,浏览器会执行默认同步提交行为——直接刷新页面并跳转,这会中断你发起的异步fetch请求:
- 首次提交时,页面立刻刷新,
fetch请求还没完成就被终止,所以控制台无输出; - 页面刷新后URL变成
http://127.0.0.1:8000/?(表单默认是GET提交,未指定action和method时,会把空表单参数拼到URL后); - 后续提交时,页面刷新前
fetch请求可能刚好触发中断错误,所以.catch执行,但error对象因请求中断没有有效信息。
核心问题2:fetch请求缺少必要请求头
你用JSON.stringify把请求体转成了JSON,但未设置Content-Type: application/json请求头,后端可能无法正确解析请求体,导致返回错误响应,这也会让.then无法正常执行(fetch仅在网络故障时触发.catch,后端返回4xx/5xx状态码不会自动抛出错误)。
修复步骤
- 阻止表单默认提交行为
在submitEmail函数开头添加event.preventDefault(),阻止页面刷新:
function submitEmail(event) { // 阻止表单默认提交行为 event.preventDefault(); fetch('/emails', { method: 'POST', // 添加请求头,告知后端请求体为JSON格式 headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ recipients: 'person@example.com', subject: 'Hello', body: 'Hello, world!' }) }) .then(response => { // 手动判断响应状态,非2xx状态抛出错误进入catch if (!response.ok) { throw new Error(`HTTP错误!状态码: ${response.status}`); } return response.json(); }) .then(result => { console.log(result); // 现在可以正常输出了 }) .catch(error => { console.log('错误: 发生了异常', error); // 现在能拿到具体错误信息 }); }
添加JSON请求头
在fetch配置对象中加入headers字段,确保后端能正确解析JSON请求体。手动处理HTTP错误状态
fetch不会因后端返回4xx/5xx状态码自动触发.catch,需在第一个.then中判断response.ok,手动抛出错误,让异常能被.catch捕获。
额外优化:使用表单实际输入值
目前代码硬编码了提交内容,可改为读取表单实际输入值:
function submitEmail(event) { event.preventDefault(); // 获取表单输入值 const recipients = document.querySelector('#compose-recipients').value; const subject = document.querySelector('#compose-subject').value; const body = document.querySelector('#compose-body').value; fetch('/emails', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ recipients, subject, body }) }) .then(response => { if (!response.ok) { throw new Error(`HTTP错误!状态码: ${response.status}`); } return response.json(); }) .then(result => { console.log(result); // 提交成功后重置表单 document.querySelector('#compose-form').reset(); }) .catch(error => { console.error('提交失败:', error); }); }
内容的提问来源于stack exchange,提问作者tices
相关产品推荐
相关产品推荐

