How to check if javascript function is ready/done (jQuery) - javascript

I am working on a learning planner which gets its data (languagekeys, tasks, activities, etc.) from a database. Because I need a JSON string, I encode it with json_encode to work with it in JavaScript.
I have a different function (for keys, tasks, activities, etc.) which gets this data and writes it into an array.
function get_tasks(start_date,end_date){
maxsubtasks=0;
maxtasks=0;
$.getJSON(json_data+"?t_startdate="+start_date+"&t_enddate="+end_date, function(data) {
tasks=new Array();
$.each(data.tasks, function(i,item){
tasks[i]= new Object();
tasks[i]["t_id"]=item.t_id;
tasks[i]["t_title"]=item.t_title;
tasks[i]["t_content"]=item.t_content;
. . .
if ( i > data.tasks.length) return false;
maxtasks = data.tasks.length;
if(item.t_parent > 0){
maxsubtasks++;
}
});
});
return true;
}
Everything is working just fine. I need some help, because I now have to call this function in $(document).ready(). I want to build my learning planner only once the function get_tasks() is complete (the array is filled with data). Otherwise, I will get errors.
How can this be solved?
Here is what I have in $(document).ready():
if(get_tasks(first_day,last_day) && get_tmp_data()){ // If this function is done
// This function should be fired -- just like a callback in jQuery
init_learnplanner();
}

You can add a callback to the function:
function get_tasks(start_date, end_date, callback) {
Then after populating the array in the function, call the callback function:
if (callback) callback();
Now you can use the callback parameter to initialise the learning planner:
get_tasks(first_day, last_day, function() {
init_learnplanner();
});

You should be able to specify a callback in $.getJSON, which gets executed as soon the request is completed.
EDIT:
You're already doing this, but why don't you just call the second code block from the end of the callback funciton in $.getJSON?

Other answers haven't worked for me because I have 5 functions which use my data with $.getJSON, and I need to have collected all information to even start init_learnplanner().
After several hours of searching, I've discovered the jQuery function ajaxComplete, which works like a charm for me. jQuery tracks all ajax calls that have been fired and triggers anything assigned .ajaxComplete() when one is complete.

What I'm doing is usually something like this:
simple, looks like beginner but it works :) :D
<script type="text/javascript">
var isBusy = true;
$(document).ready(function () {
// do your stuff here
isBusy = false;
});
function exampleajax() {
if(isBusy) return false;
isBusy=true;
$.ajax({
async: true,
type: 'POST',
url: "???.asp",
dataType: "jsonp",
data: qs,
error: function(xhr, ajaxOptions, thrownError){
//console.log(xhr.responseText + " AJAX - error() " + xhr.statusText + " - " + thrownError);
},
beforeSend: function(){
//console.log( "AJAX - beforeSend()" );
},
complete: function(){
//console.log( "AJAX - complete()" );
isBusy = false;
},
success: function(json){
//console.log("json");
}
});
}
</script>
hope this help you

Related

how to execute a specific code after a ajax

I have a function in which uses ajax which populate a select element of options from my database, here is the code of the function.
function Filtering_GetRole(roleElement) {
$.ajax({
type: "POST",
url: "IROA_StoredProcedures.asmx/Filtering_GetRole",
data: "",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
var roletooldetails = response.d;
var appendItem = "";
$(roleElement).empty();
$.each(roletooldetails, function (index, Filtering_GetRoleInfo) {
var activeappend = "";
var id = Filtering_GetRoleInfo.id;
var role = Filtering_GetRoleInfo.Role;
activeappend = "<option value=" + id + ">" + role + "</option>";
appendItem += activeappend;
});
$(roleElement).prepend('<option disabled="disabled" selected="selected" value="">Select Tool</option>')
$(roleElement).append(appendItem);
},
error: function (XMLHttpRequest) {
console.log(XMLHttpRequest);
alert("error in Filtering_GetTool");
}
});
}
which I call like this
var slcRole = $(this).closest(".td-span-buttons").closest(".tr-span-buttons").find(".slc-role"); var holdRoleId = slcRole.val();
Filtering_GetRole(slcRole);
slcRole.val(holdRoleId);
but the problem is since I use ajax the code slcRole.val(holdRoleId); will execute first resulting to the value not selected on the option element. How can I do that when the ajax code finished this code will execute. Sorry for the bad english
The another way to make sure your ajax request has been processed is to use jQuery.when(), but the best way is to put slcRole.val(holdRoleId) into success callback.
Just put slcRole.val(holdRoleId); into success.
Else, js will execute without waiting ajax done.
I think you need to execute this after success or error so instead putting in any callback or after your Filtering_GetRole put it in the complete callback of ajax have a look here. It will execute code within complete block when ajax is complete. Hope this will help.
You can use complete function. complete executes only after the "success" of ajax. Following code will be helpful to you.
success: function (response) {
// Your code
},
complete: function (response) {
slcRole.val(holdRoleId);
},
error: function (XMLHttpRequest) {
// Your code
}

Button Doesn't Work After Second Click

I have a button that calls a function in javascript. The javascript in turn runs two consecutive ajax calls. After the first one finishes, it does some extra work, then runs the second ajax call.
The button works upon first clicking it. However, when I want to click it again the following error pops up...
Uncaught TypeError: object is not a function
It is in reference to my function that is being called 'onclick' from the button.
I am pretty new to ajax but I'm sure that this shouldn't be happening. Other buttons are working just fine, and they all call functions from the same script. It just seems to be this one function. I would have expected there to be a semicolon missing or something, but then the first time wouldn't have worked... Also, I do know that the function finished executing, since I debugged the function and it reaches the bottom...
Here are my ajax calls in case you're interested...
var $response = $.ajax({
url: $abs_filename,
type: 'HEAD',
async: false,
success: function () {
console.log('done');
}
}).status;
($response != "200") ? $exist = false : $exist = true;
....lots of extra code here
....
var response = $.ajax({
type: 'POST',
url: '/SERT/includes/file_operations.php',//url of receiver file on server
data: {saves: $save_data}, //your data
dataType: 'text', //text...
success: function(res) {
alert(res);
},
async: false
}).status;
EDIT:
My function is called by
<input type="button" .... onclick="save_session()">
You've not actually shown the code that is causing the error.
However...
Don't do this; it doesn't do what you think it does.
($response != "200") ? $exist = false : $exist = true;
Do this:
$exist = $response == "200";
And just DON'T use synchronous XHR.
I was able to figure it out...
So I had a jQuery append operation going on inside of the save_session() function. This operation was as such...
$bottom_section.append('<input type="hidden" name="save_session" value="' + $total + ' ' + $paragraph + '">');
When I took this out then the whole thing worked as expected. My guess is that by naming the input "save_session" messed with the function definition of save_session() in memory. Now there wasn't a definition conflict, then it was okay.

Calling Javascript Functions In Order

I'm trying to use a button to perform an API Call to Flickr, like so:
$(document).ready(function (){
$('#goButton').click(function (){
makeAPICall();
});
});
This works as expected, but the communication between the client and the Flickr API takes a while to execute, so the page appears like it is hung. I would like to add a "Working Notice" that is displayed immediately on button click to let the user know that their action is processing.
To do this, I added an H1 tag:
<h1 id="notice"></h1>
and a function that changes the inner HTML to display a notice:
function workingNotice() {
document.getElementById("notice").innerHTML="I am getting your results";
}
But when I try to edit the code for the button to something like this:
$(document).ready(function (){
$('#goButton').click(function (){
workingNotice();
makeAPICall();
});
})
The Working Notice is never displayed until the API Call has completed, which defeats the purpose.
I then tried using:
$(document).ready(function (){
$('#goButton').click(function (){
$.when(
workingNotice()
).then(
makeAPICall()
);
});
})
This gives the exact same results, where the Working Notice is not called until the API Call completes. Is there any alternative that I can try to force the order of these functions to comply?
UPDATE/EDIT:
While I found the solution to the initial problem in another answer, I know there's a reasonable chance the delay in the API Call processing is due to some mistake in this function. Here is the code for makeAPICall:
//call Flickr api and look for tags matching user search term
function makeAPICall(){
//get value tag from team 1 search box
var searchTag1 = escape(document.getElementById("searchTag1").value);
//get value tag from team 2 search box
var searchTag2 = escape(document.getElementById("searchTag2").value);
//build api call url with searchTag1
var url1 = "http://api.flickr.com/services/rest/?"
+ "method=flickr.photos.search&api_key=XXX&tags="
+ searchTag1 + "&sort=interestingness-desc"
+ "&safe_search=1&has_geo=1&format=json&nojsoncallback=1";
//build api call url with searchTag1
var url2 = "http://api.flickr.com/services/rest/?"
+ "method=flickr.photos.search&api_key=XXX&tags="
+ searchTag2 + "&sort=interestingness-desc"
+ "&safe_search=1&has_geo=1&format=json&nojsoncallback=1";
//make call to flickr api
$.when(
$.ajax({
dataType: "json",
url: url1,
async: false,
success : function(callReturn1) {
callData1 = callReturn1;
numResults1 = parseInt(callData1.photos.total);
}
}),
$.ajax({
dataType: "json",
url: url2,
async: false,
success : function(callReturn2) {
callData2 = callReturn2;
numResults2 = parseInt(callData2.photos.total);
}
})
).then(
drawChart()
);
}
Note "callData1", "callData2", "numResults1" & "numResults2" are all global.
If your makeAPICall is not async - call it out of bounds:
workingNotice();
setTimeout(makeAPICall, 1);

Call the ajax function again after Complete function

I'm trying to re-execute the function with other parameter in the complete callback, but it isn't working as I want. It works well at the first call, but when I call it again, it only alerts the test alert twice and doesn't execute the function again. My intention is to execute the function with another parameter,that is the id of the element every time that the user click on the element. I appreciate if anyone could help me, what should I do? Thanks. =)
jQuery(function($){
var load_pages = function($page){
$.ajax({
type : "POST",
data : {page_name : $page},
dataType : "html",
url : "http://localhost/includes/loadpages.php",
beforeSend : function(){
$("#content").addClass("hide");
if($page.substr(0,9) == "categoria"){
$("#content").removeClass("hide");
$("#the-portfolio").remove();
}
},
success : function(data){
$data = $(data);
if($data.length){
if($page == 'lista_portfolio'){
$(".submenu").append($data);
$(".submenu").append('<div class="end"></div>');
}
else{
if(!$("#content") == false){
$("#wrapper").append('<div id="content"></div>');
}
$("#content").append($data);
$(".foot").animate({bottom: 0},700,'easeOutExpo');
$data.fadeIn(500);
}
}
},
error : function(jqXHR, textStatus, errorThrown) {
alert(jqXHR + " :: " + textStatus + " :: " + errorThrown);
},
complete : function() {
$("#portfolio_categories_list li a").click(function(){
alert("test");
$categoria = $(this).attr("title").split("Ver todos os posts arquivados em ");
load_pages("categoria"+$categoria[1]);
return false;
});
}
});
}// end load_pages
});
Try not to call load_pages() on complete because it causes a Recursive function which can make you run out of memory.
Instead, call your function out of the $.ajax and then by binding the event click, like this.
$(document).on("click","#portfolio_categories_list li > a",function(e){
e.preventDefault();
alert("test");
$categoria = $(this).attr("title").split("Ver todos os posts arquivados em ");
load_pages("categoria"+$categoria[1]);
});
Did not see why you adding the event handler in complete callback, bind the event after you append the element to the dom in success callback should work well. And please provide some console/XHR requests output to help check your problem, put more console log instead of alert will help to track the problem

Error in Javascript return

I want to receive HTML code in chat.openChat() from chat.getHtmlPage() but return operation is "undefined".
var chat = {
openChat : function($url){
$('#popup').html(chat.getHtmlPage($url)); // It's wrong, UNDEFINED.
},
getHtmlPage : function($url){
$.ajax({
url: $url
}).done(function($html) {
return $html; // It's OK! $html is with correct html, see with alert().
});
}
}
$(document).ready(function(){
$('.btnChat').click(function(){
chat.openChat($(this).attr('href')); // It's OK!
...
return false;
});
});
By default AJAX request is asynchronous, so it ends after you get result from getHtmlPage. Even if you change it to be synchronous, you will still have undefined in openChat, because you return value from done handler, not from getHtmlPage.
You should provide a callback to getHtmlPage method. Example:
var chat = {
openChat : function($url){
chat.getHtmlPage($url, function(html) {
$('#popup').html(html);
});
},
getHtmlPage : function($url, callback){
$.ajax({
url: $url
}).done(callback);
}
}
Ajax calls are asynchronously, that's why you can't use the return of the ajax function immediately. to store the result in $('popup').
You will have to do something like this:
openChat : function($url){
chat.getHtmlPage($url));
},
setHtmlPage : function ($html) {
$('popup').html($html);
},
getHtmlPage : function($url){
$.ajax({
url: $url
}).done(function($html) {
chat.setHtmlPage($html);
});
}
You may also want to have a look to the jquery documentation about ajax. There is a way to make ajax requests synchronously, but that will block your browser and it's deprecated in the newer versions. (and it's not really ajax after all)
Check the part about async
It should be like this:
var chat = {
openChat : function($url){
chat.getHtmlPage($url);
},
getHtmlPage : function($url){
$.ajax({
url: $url
}).done(function($html) {
$('#popup').html($html);
});
}
}
$(document).ready(function(){
$('.btnChat').click(function(){
chat.openChat($(this).attr('href')); // It's OK!
...
return false;
});
});
AJAX is asynchronouse. Once you call it, script exection goes to next line and .done is called later, after request is finished. Also, return from done will do nothing. As it's jquery ajax event triggered after request is done. And jquery will not pass returned value to upper level of code even if you will make it work in synchronouse way.
The first 'A' in AJAX is 'Asynchronous', this means: by the time the .done() gets called, the rest of your code already moved on. With this knowledge, a return in .done() simply makes no sense.
Instead, we just deactiveate the asynchronous behaviour of AJAX, setting async: false in the .ajax-object. But be aware that this is not the original purpose of AJAX and it may cause trouble in some browsers.
Oone solution would then be to set the return into your getHtmlPage (in addtion to setting async to false!):
getHtmlPage : function($url){
//a new variable to store the ajax-result
//defining it here, so it's only visible within the scope of getHtmlPage
var html;
$.ajax({
url: $url,
async: false
}).done(function($html) {
//we use the html variable here to store the result
html = $html;
});
//finally returning the variable
return html;
}
This way, your return statement won't be executed until the ajax-call finishes.
SOLUTION
To do one general function (original idea).
var chat = {
openChat : function($url, $htmlElement){
chat.setHtmlPage($url, $htmlElement);
},
setHtmlPage : function($url, $htmlElement){
$.ajax({
url: $url
}).done(function($html) {
$($htmlElement).html($html);
});
}
}
$(document).ready(function(){
$('.btnChat').click(function(){
chat.openChat($(this).attr('href'), '#popup');
...
return false;
});
});

Categories