admin管理员组

文章数量:1024624

I develop a web application. Client side - Javascript/Typescript + AngularJS Server side - c# - asp web api 2 IIS Express as host.

I noticed a wierd issue occuring in which POST requets reach the server more than once. For example, one scenario in which requests are sent multiple times, each request for a specific folder email is sent 3 times. I also see those request sent three times in the Network tab.

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

The controller fitting method hits twice or even more, although it is called only once from the cliend side code.

Is this something configurably? IIS wierd thing? I seriously don't know where to start looking.

I develop a web application. Client side - Javascript/Typescript + AngularJS Server side - c# - asp web api 2 IIS Express as host.

I noticed a wierd issue occuring in which POST requets reach the server more than once. For example, one scenario in which requests are sent multiple times, each request for a specific folder email is sent 3 times. I also see those request sent three times in the Network tab.

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

The controller fitting method hits twice or even more, although it is called only once from the cliend side code.

Is this something configurably? IIS wierd thing? I seriously don't know where to start looking.

Share Improve this question edited Aug 28, 2016 at 10:56 asked Aug 22, 2016 at 22:02 user5326354user5326354 6
  • 3 It's unlikely that it's IIS or server side. I've seen something like this before and it turns out that the javascript event that ended up calling the $http.post was attached to the click event twice. So when the user clicked, the javascript event fired twice, which caused two POSTs to the server even though the code only looked like it should happen once. To check, view the network tab of your browser dev tools and see how many network requests there are. If two, focus on the javascript - use the browser dev tools to breakpoint the $http.post line and confirm how often that line is hit. – Chris Simon Commented Aug 23, 2016 at 1:31
  • Kindly check whether your browser is doing a preflight request or not. :) To know more about preflight please have a look here – Swagata Prateek Commented Aug 23, 2016 at 19:30
  • I checked the network tab and the requests are sent multiple times. The client side code is definitely running once, don't know what could be the reason for this to happen. – user5326354 Commented Aug 25, 2016 at 8:49
  • Something that has probably unrelated , but i would have write var myInterval = setInterval(function(){ to force the closure scope. – aprovent Commented Aug 31, 2016 at 11:10
  • 1 I assume that cleanInterval in the code sample is a typo and that you have clearInterval in your actual code. – Martin Parenteau Commented Sep 1, 2016 at 20:44
 |  Show 1 more ment

4 Answers 4

Reset to default 1 +50

In mailsService, you set an interval timer to call the Web service at every 3 seconds. Is it possible that, by the time the response has e back and the whole processing has been done, the timer has ticked once or twice and triggered the procedure again? You could test that by changing the interval to shorter and longer values and see if that affects the number of calls to the server.

One way of reducing the risk would be to call window.clearInterval at the very beginning of your success call back function, before the call to getAllMails:

scope.webService.get("url to get my own place").success(data => {
    window.clearInterval(myInterval);
    scope.myLocation = data;
    scope.isLocationInit = true;
    getAllMails();
}

Another solution would be to avoid using setInterval. You could execute scope.webService.get and wait for the response. In case of error, you would call the service again after a delay, using 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); 
            });
    })();
}

Note: I am not familiar with Typescript, so there may be a better way to implement it.

I don't have ment facility either, but what I always do is load a fresh new page right after posting forms, cause if a user hits the browser's Back button (they often do that), your form will be sent again. If you instead load a new page, your form will not load again. Not sure if your problem always happens, even with testing, in that case, I guess you need to post more code.

Is this happening in all browsers? I have recently seen a script tag with an empty src attribute cause Firefox to seemingly load the page multiple times.

I don't see a candidate for POST in your web API code you posted nor a POST call in your JavaScript as well. Am I missing something?

As you have mentioned For example, one scenario in which requests are sent multiple times, each request for a specific folder email is sent 3 times, I'm assuming its the getAllMails() method thats getting called multiple times. The reason for this is the setInterval logic in the below method:

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

    }

There is a potential chance that this call would be made multiple times - consider a scenario where the very first call (0th second) made to scope.webService.get("url to get my own place") took 6 seconds to plete - this will end up having an ajax call in the 3rd and 6th second due to the setInterval logic as the setInterval is cleared only after the success callback of the request.

If the logic behind having setInterval is as mentioned in the ment // Making this request until getting a successful response - waiting for server to go up, then I would suggest you to go for a different approach.

I'm not sure what would be your server rsponding if it is "not up", but assuming it returns some error code in that scenario (say, error code -1), then do a check in your error call back and if the error code is something related to "server is not up", then call the same method again. Something like:

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

I develop a web application. Client side - Javascript/Typescript + AngularJS Server side - c# - asp web api 2 IIS Express as host.

I noticed a wierd issue occuring in which POST requets reach the server more than once. For example, one scenario in which requests are sent multiple times, each request for a specific folder email is sent 3 times. I also see those request sent three times in the Network tab.

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

The controller fitting method hits twice or even more, although it is called only once from the cliend side code.

Is this something configurably? IIS wierd thing? I seriously don't know where to start looking.

I develop a web application. Client side - Javascript/Typescript + AngularJS Server side - c# - asp web api 2 IIS Express as host.

I noticed a wierd issue occuring in which POST requets reach the server more than once. For example, one scenario in which requests are sent multiple times, each request for a specific folder email is sent 3 times. I also see those request sent three times in the Network tab.

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

The controller fitting method hits twice or even more, although it is called only once from the cliend side code.

Is this something configurably? IIS wierd thing? I seriously don't know where to start looking.

Share Improve this question edited Aug 28, 2016 at 10:56 asked Aug 22, 2016 at 22:02 user5326354user5326354 6
  • 3 It's unlikely that it's IIS or server side. I've seen something like this before and it turns out that the javascript event that ended up calling the $http.post was attached to the click event twice. So when the user clicked, the javascript event fired twice, which caused two POSTs to the server even though the code only looked like it should happen once. To check, view the network tab of your browser dev tools and see how many network requests there are. If two, focus on the javascript - use the browser dev tools to breakpoint the $http.post line and confirm how often that line is hit. – Chris Simon Commented Aug 23, 2016 at 1:31
  • Kindly check whether your browser is doing a preflight request or not. :) To know more about preflight please have a look here – Swagata Prateek Commented Aug 23, 2016 at 19:30
  • I checked the network tab and the requests are sent multiple times. The client side code is definitely running once, don't know what could be the reason for this to happen. – user5326354 Commented Aug 25, 2016 at 8:49
  • Something that has probably unrelated , but i would have write var myInterval = setInterval(function(){ to force the closure scope. – aprovent Commented Aug 31, 2016 at 11:10
  • 1 I assume that cleanInterval in the code sample is a typo and that you have clearInterval in your actual code. – Martin Parenteau Commented Sep 1, 2016 at 20:44
 |  Show 1 more ment

4 Answers 4

Reset to default 1 +50

In mailsService, you set an interval timer to call the Web service at every 3 seconds. Is it possible that, by the time the response has e back and the whole processing has been done, the timer has ticked once or twice and triggered the procedure again? You could test that by changing the interval to shorter and longer values and see if that affects the number of calls to the server.

One way of reducing the risk would be to call window.clearInterval at the very beginning of your success call back function, before the call to getAllMails:

scope.webService.get("url to get my own place").success(data => {
    window.clearInterval(myInterval);
    scope.myLocation = data;
    scope.isLocationInit = true;
    getAllMails();
}

Another solution would be to avoid using setInterval. You could execute scope.webService.get and wait for the response. In case of error, you would call the service again after a delay, using 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); 
            });
    })();
}

Note: I am not familiar with Typescript, so there may be a better way to implement it.

I don't have ment facility either, but what I always do is load a fresh new page right after posting forms, cause if a user hits the browser's Back button (they often do that), your form will be sent again. If you instead load a new page, your form will not load again. Not sure if your problem always happens, even with testing, in that case, I guess you need to post more code.

Is this happening in all browsers? I have recently seen a script tag with an empty src attribute cause Firefox to seemingly load the page multiple times.

I don't see a candidate for POST in your web API code you posted nor a POST call in your JavaScript as well. Am I missing something?

As you have mentioned For example, one scenario in which requests are sent multiple times, each request for a specific folder email is sent 3 times, I'm assuming its the getAllMails() method thats getting called multiple times. The reason for this is the setInterval logic in the below method:

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

    }

There is a potential chance that this call would be made multiple times - consider a scenario where the very first call (0th second) made to scope.webService.get("url to get my own place") took 6 seconds to plete - this will end up having an ajax call in the 3rd and 6th second due to the setInterval logic as the setInterval is cleared only after the success callback of the request.

If the logic behind having setInterval is as mentioned in the ment // Making this request until getting a successful response - waiting for server to go up, then I would suggest you to go for a different approach.

I'm not sure what would be your server rsponding if it is "not up", but assuming it returns some error code in that scenario (say, error code -1), then do a check in your error call back and if the error code is something related to "server is not up", then call the same method again. Something like:

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

本文标签: javascriptHttp POST requests reach server more than onceStack Overflow