This question already has answers here:
Cancel/kill window.setTimeout() before it happens
(2 answers)
Closed 7 years ago.
Disclaimer : I'm not super proficient in Javascript and there's this small JS code part in my .net program.
I have 2 dropdown lists, ReportList and YearList. The first one's selected value dynamically populates the second dropdown list using AJAX. The problem is, each time a ReportList is selected it makes a query to a database. There can be at least 200 entries in ReportList and when a user uses the mousewheel on the dropdownlist, the application, as is, makes hundreds of query in a short amount of time and crashes the database. So far I have this
$('#ReportList').change(function () {
setTimeout(function () { PopulateYearsDropdownList() }, 2000);
});
I've played with stopPropagation() and it didn't work. I can't test it very efficiently since even the test DB is hosted and maintained by someone else.
I'd like to be able to scroll through without prompting as much queries as the amount of reports that have gone through. I was thinking of adding a small delay, with each function ".change" cancelling the last function call.
I think this wasn't really thought through from the beginning, but I want to fix this in the small amount of time I have.
I'd suggest assigning setTimeout to a variable (with proper scope accessibility) and using clearTimeout to stop the timeout.
To read more about setTimeout and clearTimeout.
An example would look like:
var myTimeout;
$('#ReportList').change(function () {
if (myTimeout) clearTimeout(myTimeout);
myTimeout = setTimeout(function () { PopulateYearsDropdownList() }, 2000);
});
You should either save the responses to the memory or use $.ajax's caching abilities. The latter needs that your server sends the response with proper caching headers
Not 100% sure what you are trying to do, but you can set your timeout to a variable, and then at another point in time clear the timeout.
var myTimeout = setTimeout(PopulateYearsDropdownList(), 2000);
//...some more code
clearTimeout(myTimeout); //cancels the original setTimeout
You can also use .abort() to cancel your AJAX request How to cancel/abort jQuery AJAX request?
Related
Working on a platform, to enable auto-ticketing functionality. For which a REST API request is used for ticket creation. Unfortunately, there are 2 requests popping simultaneously, which results in creating duplicated tickets.
How to handle such case and send only one of these requests?
Tried adding the 2nd request in the response callback of the first, though this does not seem to work.
if (flag == 1){
logger.debug("Node-down alarm-Request raised - +sitn_id);
clearTimeout(mouseoverTimer);
mouseoverTimer = setTimeout(function(){
logger.debug("Inside Call back function - ");
//function call for ticket creation
incidentRequest(sitn_id,confUtil.config.mule_url);
}, 10);
You really should show more of the code that makes the request, though it seems as if you are doing some ajax inside your 'incidentRequest', so I will presume that (if that isn't what you are doing, then please, show your code....) - and since you tags say javascript and jquery - well, here goes...
To stop the 'double send' in an AJAX call, it is simple:
function incidentRequest(sitn_id,confUtil.config.mule_url){
// stop the double by clearing the cache
$.ajaxSetup({cache: false});
// continue on with the AJAX call
// presuming the url you want is confUtil.config.mule_url
// and the data you want to send is sitn_id
$.post(confUtil.config.mule_url, 'sitn_id=' + sitn_id, function (data) {
// do cool stuff
});
}
Hopefully that will help you get moving. If not, then we will need more code of what is going on around all this.
i am trying to display the data fetched from database in the loop and between loop i call the function and send ajax request its not working.Actually its displays the only if i used alert command. If i used alert then the browser display the div and then alert if i clicked ok then it displays the second div then again show alert.
Here is the js code
function like(divid,id,session) {
var orgnldiv=document.getElementById(divid);
var ndiv=document.createElement('DIV');
var idd=id+5000;
ndiv.id =idd;
ndiv.className="likeclass";
orgnldiv.appendChild(ndiv);
var dynamicdiv=document.getElementById(idd);
var span=document.createElement('span');
var spanid=idd+5000;
span.id=spanid;
span.className="spanclass";
dynamicdiv.appendChild(span);
var xmllhttp15;
if (window.XMLHttpRequest) {
xmlhttp15=new XMLHttpRequest();
} else {
xmlhttp15=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp15.onreadystatechange = function() {
if (xmlhttp15.readyState==4 && xmlhttp15.status==200) {
document.getElementById(spanid).innerHTML=xmlhttp15.responseText;
}
}
xmlhttp15.open("GET","spancount.php?postid="+id+"&userid="+session);
xmlhttp15.send();
// alert(spanid);
}
please suggest me what can be the reason of this problem my code is working well only if i use alert
The reason why your code works when you use alert is because whenever the alert function is called. The program flow is paused. In other words, your loop wont continue to make another Ajax call until you dismiss the alert.As a result, the request gets handled properly and the response data appears in the span div. that is why I had mentioned to make your calls synchronous instead.
So to answer the question you asked in the comment, Yes at times too many Ajax calls can be a problem. Let's say that the loops runs more than 15-20 times, that means 15-20 simultaneous requests. Now, think about the number of times the same request is being handled by the php script? Definitely a problem here!
Even with Jquery Ajax, the chances of the loop completing successfully is also 50-50 actually because it all boils down to the amount of requests being made , the bandwidth being used and how the request is being processed at the server.
One possible way to fix this problem is : Rather than constantly requesting small peices of data again and again from the server in the loop, Make one Ajax call and get the entire data as json. Then, parse the json and append data to the spans by using the particular span id to extract the relevant data from the json object.
You might have to do a little bit of tweaking in both the above javascript and spancount.php . But it will definitely Save you A LOT of bandwidth. You gotta consider the fact that more than one person could be using your site!!
Hope that cleared up things, all the best with your project :D
I'm sending an ajax request to the server on user's input to an <input> element, like this:
$('#my-input').bind("input", function(event){
// here's the ajax request
});
What bothers me is that it send unnecessarily many requests on every user's keyup, meaning that if the user types very fast, there are many unnecessary requests. So I get the idea that there should be a certain delay/timeout, which waits a certain time (50 miliseconds?) for the user to stop typing before sending the ajax request. That would be one problem solved.
But what about cases when the first ajax request haven't been completed before sending another request? (Typing 60 ms / char while ajax request taking 300 ms).
What is the best way to solve this problem (both idea- and code-based)?
You can use throttle function in underscore library. As its documentation says:
Creates and returns a new, throttled version of the passed function, that, when invoked repeatedly, will only actually call the original function at most once per every wait milliseconds. Useful for rate-limiting events that occur faster than you can keep up with.
Even if you don't want to introduce a new library, you can still get idea about how this function works from its source code. In fact, a simple version of throttle function could be:
function throttle(func, delay) {
var timeout = null;
return function() {
var that = this, args = arguments;
clearTimeout(timer);
timeout = setTimeout(function() {
func.apply(that, args);
}, delay);
};
}
This jQuery throttle-debounce plugin is also helpful. Especially, the debounce function seems more suitable to your needs than throttle function according to its author:
Debouncing can be especially useful for rate limiting execution of handlers on events that will trigger AJAX requests
You could just use the setTimeout function. Every so often, see if the text hasn't changed, and if it hasn't, then process accordingly.
setTimeout(function() {
// Do something after 1 second
}, 1000);
You can set async: false in your ajax request so it will process second ajax call only after completion of first ajax request.
I'd go with #HuiZeng's answer, but just in case you want a slightly modified version.
Steps
Listen to keydown using a setTimeout that you can clear.
When it fires, check if you have a previous request in queue, if so abort it and fire a new one
Example:
var inputTimer = 0, req;
function onInput(e){
clearTimeout(inputTImer);
inputTimer = setTimeout( function(){
// You have access to e here
// Cancel any previous requests
req && req.abort();
req = $.ajax({/*...Do your magic here :)*/})
}, 100)
}
I have the following kludgey code;
HTML
<input type="search" id="search_box" />
<div id="search_results"></div>
JS
var search_timeout,
search_xhr;
$("#search_box").bind("textchange", function(){
clearTimeout(search_timeout); search_xhr.abort();
search_term = $(this).val();
search_results = $("#search_results");
if(search_term == "") {
if(search_results.is(":visible"))
search_results.stop().hide("blind", 200);
} else {
if(search_results.is(":hidden"))
search_results.stop().show("blind", 200);
}
search_timeout = setTimeout(function () {
search_xhr = $.post("search.php", {
q: search_term
}, function(data){
search_results.html(data);
});
}, 100);
});
(uses the textchange plugin by Zurb)
The problem I had with my original more simple code was that it was horribly unresponsive. Results would appear seconds later, especially when typed slower, or when Backspace was used, etc.
I made all this, and the situation isn't much better. Requests pile up.
My original intention is to use .abort() to cancel out whatever previous request is still running as the textchange event is fired again (as per 446594). This doesn't work, as I get repeated errors like this in console;
Uncaught TypeError: Cannot call method 'abort' of undefined
How can I make .abort() work in my case?
Furthermore, is this approach the best way to fetch 'realtime' search results? Much like Facebook's search bar, which gives results as the user types, and seems to be very quick on its feet.
You'd do well to put a small delay in before sending the request. If the user hits another key within 100ms (or some other time of your choosing) of the last there is no need to send the request in the first place.
When actually sending the request you should check to see if one is already if active. If it is, cancel it.
e.g.
if (search_xhr) {
search_xhr.abort();
}
don't forget to reset that var on a successful retrieval. e.g. delete search_xhr;
What Javascript event can I use for handling real time updates on a web page with ajax?
For example; Mouse_move would create frequent ajax post requests. I need a timer event, like in each 5 seconds, update notifications, check if new notification available.
Use the setTimeout function and replace alertMsg() with your ajax function. See the tutorial here: http://www.w3schools.com/js/js_timing.asp
function timeMsg()
{
var t=setTimeout("alertMsg()",5000);
}
function alertMsg()
{
alert("Hello");
}
You don't need events at all. See setTimeout or setInterval.