how to stop a setInterval after I got my server response? - javascript

I'm trying to stop my setInterval() call. The best would be to identify whenever my AJAX request is fulfilled. So, If I got my AJAX GET response, then clearinterval().
$(document).on('submit', '#post-form', function(e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: '/send',
data: {
room_name: $('#room_name').val(),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
},
success: function(data) {
//alert(data)
}
});
$(document).ready(function com() {
loop = setInterval(function() {
$.ajax({
type: 'GET',
url: "/trafic",
success: function check(response) {
//SOME CODE//
},
error: function(response) {
//SOME CODE//
}
});
}, 1000)
setTimeout(clearInterval(loop), 10000);
})
});
I tried to set a timeout, but it is very imprecise as it may take longer/shorter than the delay. So I would need something like if GET successful {clear interval()}

You need to move the clearInterval() call into the success callback of the AJAX call. You'll also need to move the loop interval higher up in your code so that it can be referenced from the success callback.
I'm also not sure why the loop interval is wrapped in a $(document).ready() call, because you can be assured that the document is ready if it is submitted. Also, the variable loop is awfully ambiguous. Try using the name of the API endpoint instead, like traffic.
Try this code:
$(document).on('submit', '#post-form', function(e) {
e.preventDefault();
const traffic = setInterval(function() {
$.ajax({
type: 'GET',
url: "/trafic",
success: function check(response) {
clearInterval(traffic);
},
error: function(response) {
//SOME CODE//
}
});
}, 1000);
$.ajax({
type: 'POST',
url: '/send',
data: {
room_name: $('#room_name').val(),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
},
success: function(data) {
// some code
}
});
});

Can I ask you first why did you use setInterval on this HTTP request ? You are probably using more computation power than you need.
You should probably make the request async (e.g https://petetasker.com/using-async-await-jquerys-ajax)
If you want to wait for an event to appear, you may want to have a look at web sockets (https://www.tutorialspoint.com/websockets/index.htm)

Related

How to pass a variable from ajax to nested ajax

I'm sending ajax call and getting an answer that I need from the first ajax then I want to pass my result to my nested ajax, my var (result) is null in the nested ajax/settimeout fun, can I pass it ? Am I missing something ?
$.ajax({
url: '#Url.Action("getCustomerGuidId", "Document")',
type: 'POST',
cache: false,
data: { "classNum": currentclassNum},
contentType:'json' ,
dataType:'text',
success: function (result) {
alert(result);**-> is fine - not null**.
// a or result is null when I hit the getCurrentDoc- function althought I get the data I need from getCustomerGuidId function
var a = result;-> tried to pass it to a new var..IDK.. I
thought it will help... it didn't.
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
contentType:'text',
data: a,-> here it's null
success: function (data) {
}
});
}, 2000);
},
error: function (result) {
alert("fail " + result);
}
});
You can try something like this will help to pass value to nested ajax call
function test(){
var myText = 'Hello all !!';
$.get({
//used the jsonplaceholder url for testing
'url':'https://jsonplaceholder.typicode.com/posts/1',
'method':'GET',
success: function (data) {
//updating value of myText
myText = 'welcome';
$.post({
'url':'https://jsonplaceholder.typicode.com/posts',
'method':'POST',
//data.title is the return value from get request to the post request
'data':{'title':data.title},
'success':function (data) {
alert(data.title +'\n' + myText);//your code here ...
}
});
}
});
}
An old question and you've likely moved on, but there's still no accepted answer.
Your setTimeout takes an anonymous function, so you are losing your binding; if you have to use a Timeout for some reason, you need to add .bind(this) to your setTimeout call (see below)
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
contentType:'text',
data: a,
success: function (data) {
}
});
}.bind(this), 2000);
At a guess you're using a Timeout because you want to ensure that your promise (i.e. the first ajax call) is resolving prior to making the nested call.
If that's your intention, you can actually scrap setTimeout completely as you have the nested call in the first ajax success call, which only runs once the promise has been resolved (providing there isn't an error; if so, jQuery would call error rather than success)
Removing setTimeout means you won't lose your binding, and a should still be result (hopefully a is an object, otherwise your second call is also going to experience issues...)
Lastly, after overcoming the binding issue you wouldn't need var a = result; you should be able to pass result directly to your nested ajax call.
Good luck!
In the nested ajax you send a as a param name, not as a param value.
So you can try the following (change param to actual param name which your server expects):
$.ajax({
url: '#Url.Action("getCustomerGuidId", "Document")',
type: 'POST',
cache: false,
data: { "classNum": currentclassNum},
dataType:'text',
success: function (result) {
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
data: {param: result},
success: function (data) {
}
});
}, 2000);
},
error: function (result) {
alert("fail " + result);
}
});

Continuous AJAX call Blocks page, Firefox

this is first time I'm facing the issue. I have used AJAX many times.
I'm calling an AJAX to update page content. AJAX call is after each 2 sec. For some Hits it working properly but after that I'm getting following Alert on FIREFOX browser
And this happens only on FIREFOX, I'm not getting such a alert on chore browser
My Code is :
function search_by_location (location_id) {
console.log(location_id);
setInterval(function(){
$.ajax({
type:"POST",
url: "<?php echo BASE_URL.'controller/function'?>",
data:{"key":location_id},
cache:false,
success:function(data){
$("#custom_div").html("");
$("#custom_div").html(data);
search_by_location (location_id);
},
error:function(err){
console.log(err);
}
});
}, 2000);
}
What is the issue ? I think this is because multiple hits and page update. Is it cache related thing ?
The issue is because you're making the AJAX request every 2 seconds, but you're also starting a new timer every time a request completes. Therefore the number of requests you're making grows exponentially. You should remove the search_by_location() call in the success handler:
function search_by_location (location_id) {
setInterval(function() {
$.ajax({
type: "POST",
url: "<?php echo BASE_URL.'controller/function'?>",
data: { key: location_id },
cache: false,
success: function(data){
$("#custom_div").html(data);
},
error: function(err){
console.log(err);
}
});
}, 2000);
}
Also note that a better pattern to follow is to use setTimeout() on the successful completion of a request. This will stop requests from backing up on the client when they take longer to complete than the poll interval:
function search_by_location (location_id) {
$.ajax({
type: "POST",
url: "<?php echo BASE_URL.'controller/function'?>",
data: { key: location_id },
cache: false,
success: function(data){
$("#custom_div").html(data);
},
error: function(err){
console.log(err);
},
complete: function() {
setTimeout(function() {
search_by_location(location_id);
}, 2000);
}
});
}
You may also want to look in to using websockets if you require the client to always have immediate access to up-to-date data. Polling patterns can end up DDoS-ing your own server if you aren't careful.

How to run another JS method from longPolling?

How in method with longPolling:
function getNewMessagesLong() {
pollingFishingStarts();
$request = $.ajax({
type: 'POST',
url: "listenMessageLong",
data: lastIncomingMessageLongJson,
dataType: 'json',
success: function(data) {
}, complete: getNewMessagesLong})
}
on complete to run another method?:
function pollingFishingEnds() {
document.getElementById("fishing-end").src = "resources/img/fishing-end.png";
document.getElementById("fishing-start").src = "resources/img/fishing-start-empty.png";
}
With the example you posted, you could simply do something like this, adding an anonymous function that calls your "ends" method AND restarts your polling method:
function getNewMessagesLong() {
pollingFishingStarts();
$request = $.ajax({
type: 'POST',
url: "listenMessageLong",
data: lastIncomingMessageLongJson,
dataType: 'json',
success: function(data) {
},
complete: function() {
getNewMessagesLong();
pollingFishingEnds();
}
});
}
You could also change up to a window.setInterval() long-polling paradigm that would allow you to use your complete option to set your actual end method, rather than hijacking it for long-polling.
I'm assuming here that you want to call the "end" state code after the first round completion. Otherwise, there's literally no end to your polling, unless you have some server message to terminate, in which case you need to post that code for additional information.

AJAX trigger remote script then check for success-response

I've been searching my brains out but I can't seem to wrap my head around the little help I find.
I'm running a database that is being fed by data from another DB. The csv transport is handled by a third party server providing executable "flows" which compile and deliver the data.
I have a php script to handle the request (can't be done directly via Javascript because of the missing 'Access-Control-Allow-Origin' header). But this runs nicely. I can trigger the flow.
This is not the problem though.
What I want to do: trigger the flow #onClick of a button with something like this:
function trigger_func(flowID) {
$.ajax({
url: './ajaxPHP_handler.php',
data: "flowid="+flowID,
dataType: 'json',
success: function(result) {
var jsonResult = jQuery.parseJSON(result);
console.log(jsonResult.runID);
}
});
}
With the flowID and the resulting runID I want to check back like every second or so.
function check_status(flowID, runID) {
$.ajax({
url: './ajaxPHP_handler.php',
data: "flowid="+flowID+"&action=status&runId="+runID,
dataType: 'json',
success: function(result){...}
});
}
This will return the status / progress of the flow.
It will start for a few seconds with status==null, then go on to status=='running' and finally status=='success'.
I have gotten check_status() to run for i.e. 15 times with a setTimeout in a for loop within the success-function of trigger_func() and it works fine too.
But I cannot for the life of me figure out how I would link this stuff together to have it checking until status is 'success' and then stop checking, update page content and so on...
I have also fiddled with something like
trigger_func(id).done(function(result){
console.log(result);
});
This works too but still I can't think my way further to the checking every second until 'success'. I guess it comes down to getting the variable 'status' back into my loop so I can break it.
Maybe someone knows of a comprehensible example somewhere online...
You could do this:
function periodically_check_status_until_success(flowID, runID) {
setTimeout(function() {
$.ajax({
url: './ajaxPHP_handler.php',
data: { flowid: flowID, action: status, runId: runID },
dataType: 'json',
success: function(result){
if (result != 'success') {
periodically_check_status_until_success(flowID, runID);
}
}
});
}, 5000); // Five seconds
}
Note: You can use an object for the data option, rather than concatenate the string yourself.
So just keep calling it
var flowID, runID;
function trigger_func(flowID) {
$.ajax({
url: './ajaxPHP_handler.php',
data: "flowid="+flowID,
dataType: 'json',
success: function(result) {
var jsonResult = jQuery.parseJSON(result);
runID= jsonResult.runID;
check_status();
}
});
}
function check_status() {
$.ajax({
url: './ajaxPHP_handler.php',
data: "flowid="+flowID+"&action=status&runId="+runID,
dataType: 'json',
success: function(result){
if (result is not what you want) {
setTimeout(check_status,1000);
}
}
});
}
ajax are async so you have to manage by this via some 3rd party variable
Like Init with value 0
var _status = 0
than change it on your first call set it 1
function trigger_func(flowID) {
$.ajax({
url: './ajaxPHP_handler.php',
data: "flowid="+flowID,
dataType: 'json',
success: function(result) {
var jsonResult = jQuery.parseJSON(result);
console.log(jsonResult.runID);
check_status(flowID, runID);
}
});
}
function check_status(flowID, runID) {
$.ajax({
url: './ajaxPHP_handler.php',
data: "flowid="+flowID+"&action=status&runId="+runID,
dataType: 'json',
success: function(result){
//at end status=='success'.
if(status=='success'){
// end part
}else{// running
check_status(flowID, runID);
}
// clear timeout will stop that time interval after success
}
});
}

Show a loading bar using jQuery while making multiple AJAX request

I have function making multiple AJAX request with jQuery like:
function() {
$.ajax({
url: "/url",
data: {
params: json_params,
output: 'json'
},
async: false,
success: function(res) {
data1 = res
}
});
$.ajax({
url: "/url",
data: {
params: json_params,
output: 'json'
},
async: false,
success: function(res) {
data2 = res;
}
return data1 + data2;
});
}
While this function is running and data is loading I want to display a loading image without blocking it.
I have tried showing the loading icon using ajaxSend ajaxComplete, but does not work, since I have multiple ajax calls.
I also tried showing the loading at the beginning of the function and hiding at the end of the function, but failed.
How to do this?
How exactly did you try loading? Using the ajaxStart/ajaxStop events on the elements is one way to accomplish what you want. It could look like this:
$('#loadingContainer')
.hide() // at first, just hide it
.ajaxStart(function() {
$(this).show();
})
.ajaxStop(function() {
$(this).hide();
})
;
Maybe this helps you, I often used this before and it works like a charm..
I think the answer is really a combination of several of these. I would begin with ajax start to show the loading image at 0 (or whereever you want the start to be). Then I would use a callback function to increment the loading bar and repaint it.
For example
//when ajax starts, show loading div
$('#loading').hide().on('ajaxStart', function(){
$(this).show();
});
//when ajax ends, hide div
$('#loading').on('ajaxEnd', function(){
$(this).hide();
});
function ajax_increment(value) {
//this is a function for incrementing the loading bar
$('#loading bar').css('width', value);
}
//do ajax request
$.ajax({
url:"", //url here
data: {params:json_params,output:'json'},
async: false,
success: function (res) {
data1=res
ajax_increment(20); //increment the loading bar width by 20
}
});
$.ajax({
url:"", //url here
data: {params:json_params,output:'json'},
async: false,
success: function (res) {
data1=res
ajax_increment($('loading bar').css('width') + 10); // a little more dynamic than above, just adds 10 to the current width of the bar.
}
});
You could try something like this: Define a callback with a counter, and the callback hides the image after it's been called the required number of times.
showLoadingImage();
var callbackCount = 0;
function ajaxCallback() {
++callbackCount;
if(callbackCount >= 2) {
hideImage();
}
}
$.ajax({
url:"/url",
data: {params:json_params,output:'json'},
async: false,
success: function (res) {
data1=res
ajaxCallback();
}
});
$.ajax({
url:"/url",
data: {params:json_params,output:'json'},
async: false,
success: function (res) {
data2=res;
ajaxCallback();
}
});
That's only necessary for asynchronous calls, though. The way you're doing it (all your AJAX calls are synchronous), you should be able to just call hideImage() before returning at the end of your outer function.
You should be able to bind to the start and then end with the following:
$('#loading-image').bind('ajaxStart', function() {
$(this).show();
}).bind('ajaxStop', function() {
$(this).hide();
});
Or you could use beforeSend and on Complete
$.ajax({
url: uri,
cache: false,
beforeSend: function() {
$('#image').show();
},
complete: function() {
$('#image').hide();
},
success: function(html) {
$('.info').append(html);
}
});

Categories