需求:业务数据提交成功之后,根据表单 ‘项目阶段’ 字段的值发送邮件;
我的实现逻辑是这样的:在业务数据提交成功后的回掉函数中发起发送邮件的请求,然后关闭表单页面。
$.ajax({
url: url,
type: 'post',
data: {...},
dataType: 'json',
success: function (result) {
$.ajax({
url: url_email,
type: 'post',
data: {...},
dataType: 'json',
success: function () {},
error: function () {}
});
refreshGrid();//关闭当前页面,且刷新上一页面
},
error: function () {}
});
我发现发送邮件的Ajax 请求执行后返回了一个 canceled(状态码),无法成功请求后台;
网上找了很多资料,解释有如下几种情况:
1、由于 form action 事件与绑定与 submit 按钮上的 click 事件同时触发,form action 将表单内容以参数的形式追加到了 url 的末尾,而 url 变更则会导致页面重新加载,这就导致 post 请求在执行后就立即被终止!!结论:在使用到 ajax 的时候,尽量不要在 form 内使用 submit 进行提交。
2、场景未知,结论:ajax 请求默认是异步的, 将请求改为同步即可 (async: false)
我将 ajax 请求改成同步请求之后,确实能解决该问题,但是我发送邮件的请求业务是额外业务,如果发送邮件的时间过长,会影响我业务表单提交的速率。而且我不清楚为何异步请求会导致我的状态码变成 canceled。不甘心。。。
又经过一顿操作,我发现如果不关闭表单页面,即使发送邮件的请求是异步的也没关系,这时才恍然大悟:
由于发送邮件的请求是异步的,而且紧接着又关闭了表单页面,可能还没等我发送邮件请求的请求完,页面就关闭了,此时浏览器会默认该请求也不需要,所以才取消该请求。如果将发送邮件改成同步,关闭页面的操作得等请求结束后才执行,所以就不会有问题。
现在明白了我没办法在前台使用异步的 ajax 请求,只能乖乖在后台新建一个线程来发送邮件实现异步的操作:
public String pushEmail(HttpServletRequest request) {
...//数据处理
new Thread(new Runnable() {
@Override
public void run() {
try {
mailUtil.sendMailToMultiReceiver(addrs, title, text);
} catch (MessagingException e) {
System.out.println("*****************邮件发送报错****************");
e.printStackTrace();
}
}
}).start();
}