Http POST请求会多次到达服务器
Http POST请求会多次到达服务器
我开发了一个Web应用程序。
客户端 - JavaScript / TypeScript + AngularJS
服务器端 - c# - asp.net web api 2
IIS Express作为主机。
我注意到一个奇怪的问题,即POST请求到达服务器超过一次。例如,其中一个场景是每个特定文件夹的邮件请求被发送3次。在网络选项卡中,我也看到这些请求被发送了三次。
public class mailsService extends ImailsService{ static instance : ImailsService; // Dictionary of folder -> emails public Folders; public mailsService(){ var scope = this; myInterval = setInterval(function(){ // Making this request until getting a successful response - waiting for server to go up scope.webService.get("url to get my own place").success(data => { scope.myLocation = data; scope.isLocationInit = true; getAllMails(); window.cleanInterval(myInterval); }) }, 3000); } // This function happen on it's own when running the client code. // The service is a singleton therefore this code runs only once. public getAllMails() { if (!this.isLocationInit) return; var scope = this; scope.webService.get("url to get all folders").then(reponse => { var folders = response.data; for (var i = 1; i <= folders.length; i ++){ return scope.get("url to get the mails inside specific folder").then(initMails.bind(null, i)); }}); } public initMails (folderId : number, response){ mailsService.instance.Folders[folderId].push(response.data); } } public class webService extends IwebService { public get(url : string){ return this.$http.get(url); } public post(url : string, data : any){ return this.$http.post(url, data); } } // 服务器端: // 跨域请求 [EnableCors(origins: "*", headers: "*", methods: "*")] public class MailsController : ApiController { private IMailsService _mailsService; public MailsController(IMailsService service) { this._mailsService = service; } public IHttpActionResult GetAllFolders() { var result = _mailsService.GetAllFolders(); if (result == null) return BadRequest("..."); return Ok(result); } public IHttpActionResult GetFolderEmails(int folderId) { var result = _mailsService.GetFolderEmails(folderId); if (result == null) return BadRequest("..."); return Ok(result); } }
控制器适配的方法会被调用两次甚至更多,尽管从客户端代码中只调用一次。
这是可以配置的吗?是IIS的奇怪问题吗?我真的不知道从哪里开始查找。
在mailsService中,您设置了一个间隔定时器,每隔3秒调用一次Web服务。有可能在响应返回和整个处理完成之前,定时器已经触发了一次或两次,并再次触发了该过程吗?您可以通过将间隔更改为较短或较长的值来进行测试,并查看对服务器的调用次数是否受到影响。
减少风险的一种方法是在成功回调函数的开头调用window.clearInterval,在调用getAllMails之前:
scope.webService.get("url to get my own place").success(data => { window.clearInterval(myInterval); scope.myLocation = data; scope.isLocationInit = true; getAllMails(); }
另一种解决方法是避免使用setInterval。您可以执行scope.webService.get并等待响应。如果出现错误,您可以在延迟后再次调用该服务,使用setTimeout:
public mailsService() { var scope = this; (function callWebService () { scope.webService.get("url to get my own place") .success(data => { scope.myLocation = data; scope.isLocationInit = true; getAllMails(); }) .error(data => { setTimeout(callWebService, 3000); }); })(); }
注意:我不熟悉TypeScript,所以可能有更好的实现方法。
谢谢您的建议,我采用了第二种方法!
问题的原因:用户在提交表单后点击浏览器的返回按钮时,表单会再次发送,导致HTTP POST请求多次到达服务器。
解决方法:在表单提交后加载一个新页面,而不是重新加载当前页面,可以避免表单再次发送。
以下是一个导致该问题的完整场景流程:
// submit.php // 处理表单提交的代码 if ($_SERVER['REQUEST_METHOD'] === 'POST') { // 执行表单处理逻辑 // 处理完成后,跳转到一个新页面 header("Location: success.php"); exit; }
Success Form submitted successfully!
这样,无论用户是否点击返回按钮,表单都只会提交一次,避免了重复提交的问题。