React Ajax setInterval Memory leak - javascript

I looked and tried everything in the other questions. Still couldn't solve my memory leak. Here's the code. Essentially it gets a JSON file from a server and updates the table accordingly. It loops the AJAX call every 5 seconds.
Memory leak happens in this AJAX call.
Any help would be great.
LoadDataTable: function(){
$.ajax({
url: "***************************.json",
dataType: 'json',
cache: false,
timeout: 5000,
success: function(data) {
this.setState({temp1:data[2].field3}),
this.setState({temp2:data[2].field5}),
this.setState({temp3:data[2].field25}),
this.setState({temp4:data[2].field26});
if(data[2].field3 > 9 || data[2].field5 >9||data[2].field5>9 ||data[2].field26>9){
document.location.href='#/'
}
else{
//console.log("Stopped playing");
}
setTimeout(this.LoadDataTable, 5000);
}.bind(this),
error: function(request, status, err) {
//request.abort();
console.log(request);
setTimeout(this.LoadDataTable, 5000);
}.bind(this),
})
},
componentDidMount: function() {
this.LoadDataTable();
//this.setInterval(this.LoadDataTable, 100);// Call a method on the mixin
},

Try moving your success and error functions out to a named function like this:
$.ajax({
url: "***************************.json",
dataType: 'json',
cache: false,
timeout: 5000,
success: this.successTimeout,
error: this.errorTimeout,
})
componentDidMount: function() {
this.LoadDataTable();
//this.setInterval(this.LoadDataTable, 100);// Call a method on the mixin
},
successTimeout(data) {
this.setState({temp1:data[2].field3}),
this.setState({temp2:data[2].field5}),
this.setState({temp3:data[2].field25}),
this.setState({temp4:data[2].field26});
if(data[2].field3 > 9 || data[2].field5 >9||data[2].field5>9 ||data[2].field26>9){
document.location.href='#/'
}
else{
//console.log("Stopped playing");
}
setTimeout(this.LoadDataTable, 5000);
}.bind(this),
errorTimeout(request, status, err) {
//request.abort();
console.log(request);
setTimeout(this.LoadDataTable, 5000);
}.bind(this)
Also, you might want to think about using the fetch API. Just be sure to include the polyfill for browser compatibility

Related

Ending setInterval when ajax call is complete

$.ajax({
url: vars.url,
type: "post",
data: r,
async: true,
processData: vars.process,
contentType: vars.contenttype,
beforeSend: function(){
if(vars.loadbar == 'true'){
setInterval(function () {
$.getJSON(domain + '/core/files/results.json', function (data) {
console.log(data);
})
}, 1000);
}
},
complete: function(){
clearInterval();
},
succes: function(data){
..................
}
})
So I am trying to end the infinite loop my code is spawning as soon as my ajax call is being done. It now phones pretty much every second to my file to get results, which i want to stop as soon as my ajax call is completed.
I am not sure how to approach this, since if i assign a variable to the setInterval (being it in the function of the beforeSend itself, or outside of the AJAX call), it either wont see the variable, or my variable is empty. I think I am approaching this wrong. Can I check within the beforeSend if the AJAX call is complete to end the loop?
you can store your interval as a global variable and clear it when you need it. like so:
let interval;
$.ajax({
url: vars.url,
type: "post",
data: r,
async: true,
processData: vars.process,
contentType: vars.contenttype,
beforeSend: function(){
if(vars.loadbar == 'true'){
interval = setInterval(function () {
$.getJSON(domain + '/core/files/results.json', function (data) {
console.log(data);
})
}, 1000);
}
},
complete: function(){
clearInterval(interval);
},
succes: function(data){
..................
}
}

Ajax - All request are Done/Completed

I have a difficulty to know when all Ajax requests are completed because I need this information to call another function.
Difficulty are to know when my 4/5 function with requests are completed. I use native function of ajax and none is working for me.
I used Chrome, and async requests.
Someone Helps me
I use this(not work):
$(document).ajaxStop(function() {
alert("Completed");
});
and this (not Work):
$(document).ajaxComplete(function() { alert("Completed"); });
Both ways I try use in another function thal calls all requests:
Example:
function Init()
{ Search("123"); Search2("1234"); Search3("12345");
... }
Extract one (of 5 requests,others are very similar ) of my request:
function Search(user) {
$.ajax({
url: 'www.example.com/' + user,
type: 'GET',
async: true,
dataType: 'JSONP',
success: function(response, textStatus, jqXHR) {
try {
if (response != null) {
alert("Have Data");
} else {
alert("are empty");
}
} catch (err) {
alert("error");
}
},
error: function() {
alert("error");
}
}); }
have you tried putting it in a done function? something like...
$.ajax({
url: 'www.example.com/' + user,
type: 'GET',
async: true,
dataType: 'JSONP'
}).done(function (data) {
code to execute when request is finished;
}).fail(function () {
code to do in event of failure
});
bouncing off what Michael Seltenreich said, his solution, if i understand where you guys are going with this...might look something like:
var count = 0;
function checkCount(){
if(count == 5 ){
//do this, or fire some other function
}
}
#request one
$.ajax({
url: 'www.example.com/' + user,
type: 'GET',
async: true,
dataType: 'JSONP',
}).done( function(data){
count += 1
checkCount()
})
#request two
$.ajax({
url: 'www.example.com/' + user,
type: 'GET',
async: true,
dataType: 'JSONP',
}).done( function(data){
count += 1
checkCount()
})
and do it with your five requests. If that works out for you please make sure to mark his question as the answer;)
You can create a custom trigger
$(document).trigger('ajaxDone')
and call it when ever you finished your ajax requests.
Then you can listen for it
$(document).on('ajaxDone', function () {
//Do something
})
If you want to keep track of multiple ajax calls you can set a function that counts how many "done" values were passed to it, and once all are finished, you can fire the event.
Place the call for this function in each of the 'success' and 'error' events of the ajax calls.
Update:
You can create a function like so
var completedRequests= 0
function countAjax() {
completedRequests+=1
if(completedRequests==whatEverNumberOfRequestsYouNeed) {
$(document).trigger('ajaxDone');
}
}
Call this function on every success and error events.
Then, ajaxDone event will be triggered only after a certain number of requests.
If you wanna track specific ajax requests you can add a variable to countAjax that checks which ajax completed.

Long polling too fast

(function poll() {
$.ajax({
url: "/Home/Tail", success: function (data) {
console.log(data);
},
data: { datetime: getISODateTime(new Date()) },
dataType: "json",
timeout: 30000
});
})();
I have the above code, i am doing long polling to an endpoint.
However, it is too fast. Isnt it supposed to do it every timeout seconds?
However, it is too fast. Isnt it supposed to do it every timeout
seconds?
timeout property here will only timeout the call and then fire the error. If you find it too fast, you must be doing something else besides the code posted above.
In order to do a long-polling one way could be to use Javascript setTimeout when you receive a response. Also, in such cases you should have an abort figured out somewhere.
For example (this will poll every 3 seconds):
<button id="start">Start</button>
<button id="stop">Stop</button>
var timer;
function poll() {
$.ajax({
url: "/echo/json/", success: function (data) {
console.log(data);
timer = setTimeout(poll, 3000);
},
data: { datetime: new Date()},
dataType: "json",
timeout: 30000
});
};
$("#start").on("click", function() { console.log("started.."); poll(); });
$("#stop").on("click", function() { console.log("stopped.."); clearTimeout(timer); });
Fiddle: http://jsfiddle.net/abhitalks/rf0uaaLj/
You could use the timeout setting in the ajax options like this:
(function poll() {
$.ajax({
url: "/Home/Tail", success: function (data) {
console.log(data);
},
timeout: 30000,
data: { datetime: getISODateTime(new Date()) },
dataType: "json"
});
})();
Read all about the ajax options here

How to show progress bar when calling AJAX?

I am developing a mobile app using phonegap (JQ + Html ). In my app, consuming REST webservice using AJAX calls.When service invoke, I am showing a progress bar animated GIF image . The problem is, browser freezes when calling AJAX. So the progress bar is not showing.
In ‘beforeSend’ i am showing the progress bar image and after ‘complete’ i am hiding the progress bar image.
I am also trying async: true . But it execute service as asynchronously. In my app, asynchronous execution is not suit. Because asynchronous execution will not wait for ajax executing. My app should wait until the ajax execution complete. In that process time I want show progress bar.
Here is my code.
$.ajax({
type: "POST",
dataType: "json",
contentType: "application/json",
accepts: "application/json",
beforeSend: function() {
StartPBar():
},
data: JSON.stringify(RQ),
async: false,
url: URL,
complete: function() {
stopPBar();
},
success: function(res, status, xhr) {
try {
RS = res;
} catch (e) {
alert(e);
}
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert("Excpetion " + errorThrown + XMLHttpRequest);
}
});
Any suggestion to show the progress bar stay on screen until the process is fully complete? Any help would be appreciated. Thanks
Make sure you verify your javascript code.
Remove this code.
beforeSend: function() {
StartPBar():
},
Replace your jquery mobile with this one jQuery Mobile 1.4.0-rc.1
http://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.js
Replace your code with this one.
$.mobile.loading('show');
$.ajax({
type: "POST",
dataType: "json",
contentType: "application/json",
accepts: "application/json",
data: JSON.stringify(RQ),
async: false,
url: URL,
complete: function() {
$.mobile.loading('hide');
},
success: function(res, status, xhr) {
try {
$.mobile.loading('hide');
RS = res;
} catch (e) {
alert(e);
}
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
$.mobile.loading('hide');
alert("Excpetion " + errorThrown + XMLHttpRequest);
}
});
Try to set async: true, the async: false will freeze the browser until the request is completed. Also move the async: true before beforeSend method.
The async: true, when supported by browser, basically means: browser will send data asynchronous and will not block or wait other actions from executing. This is the only in my opinion way to show the progress bar indicator. Because (from the documentation):
Note that synchronous requests may temporarily lock the browser,
disabling any actions while the request is active.
If you want to wait until ajax requests done, you can do it also with async:true like;
StartPBar():
$.when(runAjax()).done(function(result) {
// result conatins responseText, status, and jqXHR
stopPBar();
});
function runAjax() {
return $.ajax({
type: "POST",
dataType: "json",
contentType: "application/json",
accepts: "application/json",
data: JSON.stringify(RQ),
async: true,
url: URL,
success: function (res, status, xhr) {
try {
RS = res;
}
catch (e) {
alert(e);
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("Excpetion " + errorThrown + XMLHttpRequest);
}
});
}
In this example, when ajax request completed, progressbar stop function will be called.

Accurate long polling example?

I've made an function that should do an long polling and fetch live data that is being "pushed" to me. Right now I'm testing against an json object that is formatted in the way that it will look once I receive the data. It seems as it is working accurate so far. I was merely wondering what you think about it? Would you refactor it somehow or do it entirely in another way?
var url = '../../path_to_script/respondents.json';
function fetchData() {
$.ajax({
url: url,
method: 'GET',
dataType: 'json',
contentType: "application/json; charset=utf-8",
cache: false,
success: function (data) {
//parseData(data);
setTimeout(function () { fetchData() }, 5000);
console.log(data);
},
error: function (data) {
setTimeout(function () { fetchData() }, 5000)
}
});
}
Regards
This works like expected. Since you've wisely choosen to fire a setTimeout once the request returned, there can't be "overlapping" requests. That is a good thing.
Anyway, you could use jQuerys "new" deferred ajax objects which is probably a little bit more convinient.
(function _poll() {
$.getJSON( url ).always(function( data ) {
console.log( data );
_poll();
});
}());
Note: .always() is brandnew (jQuery 1.6).
Edit
Example: http://jsfiddle.net/rjgwW/6/
I suggest changing the events to:
success: function (data) {
console.log(data);
},
complete: function () {
setTimeout(function () { fetchData() }, 5000)
}
The complete event is always called after success and error. This way you will only have the setTimeout line once, which is better.
I would do some changes
Change method to type, method isn't a valid parameter for $.ajax. This is an error
Remove contentType, with dataType: 'json' is enough to have those values
Do something when there's an error. Use the error parameters if you need them. For example:
.
error: function (xhr, status, errorThrown) {
alert("There was an error processing your request.\nPlease try again.\nStatus: " + status);
}
Hope this helps. Cheers

Categories

Resources