Http POST请求到达服务器不止一次

本文关键字:服务器 不止一次 POST 请求 Http | 更新日期: 2023-09-27 18:03:41

我开发了一个web应用程序。客户端- Javascript/Typescript + AngularJS服务器端- c# - asp.net web api 2IIS 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);
    }
}

// Server side:
// Cross-Origin requests
[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);
    }
}

控制器拟合方法点击两次甚至更多次,尽管它只从客户端代码调用一次。

这是可配置的吗?这很奇怪吗?我真的不知道从哪里开始找

Http POST请求到达服务器不止一次

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,所以可能有更好的方法来实现它

我也没有评论功能,但我总是在发布表单后加载一个新的页面,因为如果用户点击浏览器的后退按钮(他们经常这样做),您的表单将再次发送。如果您加载一个新页面,您的表单将不会再次加载。不确定你的问题是否总是发生,即使有测试,在这种情况下,我猜你需要发布更多的代码。

所有浏览器都会出现这种情况吗?我最近看到一个带有空src属性的脚本标签导致Firefox似乎多次加载该页面。

我在你的web API代码中没有看到POST的候选,你也没有在JavaScript中看到POST调用。我错过什么了吗?

正如你所提到的例如,一个请求被多次发送的场景,每个特定文件夹电子邮件的请求被发送3次,我假设它的getAllMails()方法被多次调用。原因是下面方法中的setInterval逻辑:

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);
    }

这个调用有可能被多次调用-考虑一个场景,第一次调用(第0秒)对scope.webService.get("url to get my own place")进行了6秒的完成-由于setInterval逻辑,这将在第3秒和第6秒结束ajax调用,因为setInterval只有在请求回调成功后才被清除。

如果setInterval背后的逻辑是在评论// Making this request until getting a successful response - waiting for server to go up中提到的,那么我建议你采用不同的方法。

我不确定什么会是你的服务器响应,如果它是"不起来",但假设它返回一些错误代码在这种情况下(说,错误代码-1),然后做一个检查在你的错误回调,如果错误代码是有关的东西"服务器不起来",然后再次调用相同的方法。比如:

public mailsService(){
        var scope = this;
        scope.webService.get("url to get my own place")
          .then(function(data)   {
                scope.myLocation = data;
                scope.isLocationInit = true;
                getAllMails();      
            },
            function(ex)
            {
              if(ex.status === "-1")
               {   
                 //service seems to be 'not up', keep hitting the service
                 mailsService();      
               }
            });
       }