So Javascript is not multithreaded. But I have the following problem.
I use AJAX calls from a function called from setTimeout. I need to know be able to distinguish when there are active AJAX calls before rescheduling the function.
For that I am using 2 global variables. So the code structure is as follows:
setTimeout(some_function, 10000);
window.ajax_running = 0;
window.calls_so_far = 0;
function some_function () {
if(window.ajax_running) {
setTimeout(some_function, 10000);
return;
}
window.ajax_running = 1;
$.ajax({
//various
success: function (data) {
window.calls_so_far = window.calls_so_far + 1;
console.log('Running calls: ' + window.calls_so_far);
if(window.calls_so_far >= SOME_VALUE) {
//we are ok ajax has finished
window.ajax_running = 0;
}
}
Simple code. The problem is that it does not work. I see in the console:
Running calls: 1
So the global variable is not being incremented. It is as is each AJAX call sees the original value 0 and increments it (like as if there were threads).
What am I messing up here? How can I fix this?
When success runs, the ajax call had already finished, so you are not running this call when u add calls_so_far.
I'm not sure why u need the call to be "counted", but if is just the other problem (to call the same function after the first had finished, i would suggest this approach:
var counter;
counter = 0;
function recallSomeFunction() {
setTimeout(some_function, 10000);
}
function some_function () {
$.ajax({
//various
success: function (data) {
if (++counter < SOME_VAL) recallSomeFunction();
//...
},
error: function ( jqXHR, textStatus, errorThrown )) {
recallSomeFunction()
//...
});
}
Related
I have the following JS code:
var delay = 5000;
function init() {
setInterval(getFileCount, delay);
}
function getFileCount() {
$.get('/notification/course-file-count', function(response) {
if (response.items.length === 0) {
return false;
}
// Do stuff with response
});
}
On page load I'm calling the init() function. The idea is to start the interval and call the getFileCount() function every 5 seconds.
So, the interval waits 5s after the page loads and runs, but it always makes the Ajax call twice.
What am I missing?
UPDATE:
I know the init() function is triggered twice on page load (thanks to the comment by Yury Tarabanko). I don't quite understand, why. The almost-full code:
$(function() {
'use strict';
function handleCourseNotification() {
var delay = 5000;
function init() {
setInterval(getFileCount, delay);
}
function getFileCount() {
$.get('/notification/course-file-count', function(response) {
if (response.items.length === 0) {
return false;
}
updateCourseList(response.items);
});
}
function updateCourseList(items) {
// update course list...
}
return {
init: init
};
}
if ($('#js-auth-course-list').length) {
var notificationHandler = handleCourseNotification();
notificationHandler.init();
}
});
It's a small module, which I initialize after page load, if a specific element is available in the DOM - $('#js-auth-course-list'). Why is init called 2 times actually? I directly call it once.
In general, it is not a good idea to call asynchronous calls inside a setInterval() because you do not know the exact response time. So, you could end up calling the second async function before the response from the first call has returned.
You can try with setTimeout() like this:
var delay = 5000;
var async = function() {
$.get('/notification/course-file-count', function(response) {
if (response.items.length === 0) {
return false;
}
// Do stuff with response
// Call the async function again
setTimeout(function() {
async();
}, delay);
});
}
async();
I have a function that uses "post" to get data from the server and process it. Amount of data varies and the function can take a long time to complete (30 seconds). I would like for the function to be called repeatedly but only 10 seconds after it has completed the previous iteration. *Result of the function is stored in a global and is used in the next iteration of the same function.
I've tried setInterval and setTimeout but neither one of those seem to give me the result I'm looking for.
Any thoughts?
function foo(){
$.post( "test.php", { name: "John", time: "2pm" })
.done(function( data ) {
// do your stuff with returned data
// and call itself again...
setTimeout(foo, 10000);
});
}
Wouldn't this approach work?
function a(){
//do stuff
setTimeout(a, 10000); //has to be at the end of the execution. If you're doing things asynchronously that's a different story.
}
function setTimeout() can be used for this. But the method must be invoked for the first time then the function itself invoke the method again.
function method(){
console.log('method invoked');
setTimeout(method, 10000);
}
method();
var $id = 1;
var Interval ;
$(function(){
callAjax();//Starts Interval
});
functoin callAjax()
{
Interval = setInterval(function () {
try {
if($id > 0)
{
$.ajax({
url: _MyUrl + $id,
success: function (calbkData) {
$id = 0;
if (parseInt(calbkData.id) > 0) {
$id = calbkData.id;
OpenMsg(calbkData.id);
}
},
global: false, // this makes sure ajaxStart is not triggered
dataType: 'json'
//,complete: longpoll
});
}
} catch (e) {
// alert(e);
}
}, 10000);
}
This is working very fine, for me.
function Test()
{
//Your code here
setTimeout(Test(),10000);
//Its used to set time interval after your iteration is run
}
I am trying to create a recursive function in Javascript. But in order to loop my XML file properly I am trying to pass the right value taken from the XML length and pass it to the setTimeout function.
The problem is that the setTimeout ( setTimeout('cvdXmlBubbleStart(nextIndex)', 3000);
)function does not get the value of nextIndex and thinks it is undefined. I am sure I am doing something wrong.
jQuery(document).ready(function($) {
cvdXmlBubbleStart('0');
});
function cvdXmlBubbleStart(nextIndex) {
$.ajax({
url: "cross_video_day/xml/broadcasted.xml",
dataType: "xml",
cache: false,
success: function(d) {
broadcastedXML = d;
cvdBubbleXmlProcess(nextIndex);
}
});
}
function cvdBubbleXmlProcess(nextIndex) {
var d = broadcastedXML;
//console.log(nextIndex);
var length = $(d).find('tweet').length;
if((nextIndex + 1) < length) {
nextIndex = length - 1;
$(d).find('tweet').eq(nextIndex).each(function(idx) {
var cvdIndexId = $(this).find("index");
var cvdTweetAuthor = $(this).find("author").text();
var cvdTweetDescription = $(this).find("description").text();
if (cvdTweetAuthor === "Animator") {
$('#cvd_bubble_left').html('');
obj = $('#cvd_bubble_left').append(makeCvdBubbleAnimator(cvdIndexId, cvdTweetAuthor, cvdTweetDescription));
obj.fitText(7.4);
$('#cvd_bubble_right').html('');
setTimeout('$(\'#cvd_bubble_left\').html(\'\')', 3000);
} else {
$('#cvd_bubble_right').html('');
obj = $('#cvd_bubble_right').append(makeCvdBubble(cvdIndexId, cvdTweetAuthor, cvdTweetDescription));
obj.fitText(7.4);
$('#cvd_bubble_left').html('');
setTimeout('$(\'#cvd_bubble_right\').html(\'\')', 3000);
}
});
}else{
$('#cvd_bubble_left').html('');
$('#cvd_bubble_right').html('');
}
//broadcastedXMLIndex++;
setTimeout('cvdXmlBubbleStart(nextIndex)', 3000);
}
Using an anonymous function will work because it shares the same scope as nextIndex.
setTimeout(function(){cvdXmlBubbleStart(nextIndex);}, 3000);
The reason that your current code does not work for you is because when you use a string inside of the setTimeout function it uses the Function constructor to create a function based on the string passed (which is similar to using eval and is not best practice). What is worse here is that the function created with Function will not share the same scope as where it was created and thus not have access to nextIndex.
Checkout How can I pass a parameter to a setTimeout() callback? - basically you need to pass an anonymous function to the set timeout call
setTimeout(function(){
cvdXmlBubbleStart(nextIndex)
}, 3000);
Can someone please explain to me what is wrong with my code below? I am declaring a public variable and setting it to a setTimeout, and if not null, clearing the timeout before it gets set again. When I try to clear the timeout I get undefined so the timeout continues to run.
var usernameCheckTimeout = null;
$(document).ready(function(){
$("#username").on("keyup", function(e){
if($(this).val().length >= 6)
{
if(usernameCheckTimeout != null)
{
clearTimeout(usernameCheckTimeout);
}
usernameCheckTimeout = setTimeout(isUsernameAvailable($(this).val()), 1000);
}
});
});
function isUsernameAvailable(username)
{
$.ajax({
url : "/account/username-check",
method : "POST",
dataType : 'json',
data : {
'username' : username
}
}).done(function(data) {
console.log(data);
});
};
You do not need to do the null check also you need to create a closure around this, otherwise this will refer to not what you think this actually is.
var usernameCheckTimeout;
$("#username").on("keyup", function (e) {
if ($(this).val().length >= 6) {
clearTimeout(usernameCheckTimeout);
var that = this;
usernameCheckTimeout = setTimeout(function () {
isUsernameAvailable($(that).val();
}, 1000);
}
});
Some jsfiddle love like usual.
The timeout is being cleared. The problem is that you are calling your function immediately instead of passing the function to setTimeout.
setTimeout(isUsernameAvailable($(this).val()), 1000);
isUsernameAvailable($(this).val()) will be called and the result of this call will be passed to setTimeout.
You should instead pass a function which calls this function:
EDIT: As #Mark said, you also need to deal with this not being what you expect:
var value = $(this).val();
setTimeout(function(){
isUsernameAvailable(value)
}, 1000);
You have a couple of issues. The first issue, which is huge, is that you are executing isUsernameAvailable($(this).val()) immediately and passing the return value to setTimeout - you need to move this into an anonymous function so it does not execute until the anonymous function is called by the timeout:
usernameCheckTimeout = setTimeout(function () {
isUsernameAvailable($(this).val());
}, 1000);
the javascript timeout functions rely on numeric IDs to function. You should avoid testing for null or undefined or anything else, and instead test for a number:
// leave it as undefined
var usernameCheckTimeout;
...
if (typeof usernameCheckTimeout === 'number') {
clearTimeout(usernameCheckTimeout);
}
Ok. here's the scenario:
function DataFeed(){
function PopulateData()
{
$('div#example').load('http://www.example.com', fxnCallBack);
};
function fxnCallBack()
{
PopulateData();
}
this.activator = function() {
PopulateData();
}
};
var example_obj = new DataFeed;
example_obj.activator();
In the above code, the ajax .load gets executed once, then callback executes. But the callback doesn't start the ajax function again?
Thanks in advance.
edit- why doesn't it display new line properly -.-
InternalError: too much recursion
JavaScript engines normally have a max limit in the number of recursions or the time recursive execution may take. Use setInterval instead:
function DataFeed() {
var interval;
function PopulateData() {
$('div#example').load('http://www.example.com', function(data) {
if(data == "clear_interval")
interval = clearInterval(interval); // clear the interval
});
}
this.activator = function() {
interval = setInterval(PopulateData, 1000); // run every second
};
}
var example_obj = new DataFeed();
example_obj.activator();