Reputation:
I develop a web application. Client side - Javascript/Typescript + AngularJS Server side - c# - asp.net 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.
Upvotes: 7
Views: 3750
Reputation: 6440
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 complete - 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 comment // 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();
}
});
}
Upvotes: 0
Reputation: 73761
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 come 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.
Upvotes: 1
Reputation: 521
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.
Upvotes: 0
Reputation: 524
I don't have comment 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.
Upvotes: 0