Both of the functions are $.getJSON() functions, and even though my first function is placed before the other one, it sometimes occurs after the second one. Note that I mentioned "sometimes". When I keep refreshing the page, I get different results, and it's like it's randomly being chosen which function is called first. Here is the snippet of code:
timeClusters = [];
$.getJSON('java_output/tasksTab.json', function (data) {
console.log ("first");
// Method stuff here, not important
});
$( document ).ready(function() {
console.log("second");
// Method stuff here, not important
});
Now, when I run the program and look at the console, sometimes I get
first
second
but other times I get
second
first
It is essential that I get the first one first, and second second, because the second method processes data that is produced and altered in the first method.
Let me know if you need more information
The getJSON method is Asynchronous, that means that once started it will eventually hold a result, the function wrapped in document ready instead fires as soon as the DOM is ready, instead of doing this sequence of action you should move the code form the ready function to the getJSON callback:
$(document).ready(function() {
$.getJSON('java_output/tasksTab.json', function (data) {
console.log ("first");
}).done(function() {
console.log( "second" );
})
})
As adeneo pointed out you don't actually need to chain the done method, you can simply add the computation in the default callback:
$(document).ready(function() {
$.getJSON('java_output/tasksTab.json', function (data) {
console.log ("first");
console.log( "second" );
})
})
Other kinds of callback you can use are fail and always.
Related
I have three functions that all work with data from a global object. This global object gets filled with data from a local array in one function and with data from an ajax request with the second function. The third function relies on the data in the object, so the ajax request must have been completed.
I believe I am misunderstanding callbacks. Here's what I do:
var currentCharacter = {}
// this function gets the local data and then calls the second function
function loadData(getMarvelData) {
// do things to fill currentCharacter
getMarvelData(); // this is the callback to the next function (no ?)
}
// this function performs the ajax request, then calls the third function
function getMarvelData(getGoogleMap) {
// do ajax request and add stuff to currentCharacter
getGoogleMap(); // this is the callback to the final function (no ?)
}
function getGoogleMap() {
// do Google Map related stuff with data from currentCharacter
}
I thought setting a function as an argument of another function and then executing it would make the function dependent on the other before it continues. Clearly I still misunderstand callbacks after trying to make it work for a week now. As it is, the getMarvelData function doesn't even get called because I never see the alert popup and the currentCharacter object only has data from the loadData function.
Could somebody show the correct approach for my code, or if my approach of making these three functions is even the right one for this scenario.
The full repository is available at: https://github.com/ChaMbuna/Marvel-Map
V0.9 was actually working but the ajax call was set to run synchronous (it still is btw) Since then I've been overhauling my code to make it work asynchronously and to remove all jQuery (this is a Udacity project and removing jQuery was suggested by an instructor).
Appreciate the help
I have not enough reputation to put a comment, but a wild guess, you should remove the argument in loadData&getMarvelData or actually pass a function in calls to those function.
You have to pass the parameters correctly.
Try this:
var currentCharacter = {}
loadData(getMarvelData, getGoogleMap);
function loadData(f1, f2) {
// do sth.
f1(f2);
}
function getMarvelData(f2) {
// do sth.
f2();
}
function getGoogleMap() {
// do sth.
}
I havn't tested it, but it should work.
I am using File APIs with Javascript.
I need to wait for the completation of onload method, how can I do it?
reader.onload = function (e) {
contents = reader.result;
var addAttchCallBack = loadRequestExecutor();
addAttchCallBack.done(function (data) {
alert("ok");
})
};
alert("Ko");
I see always before "Ko"
N.B: the function loadRequestExecutor() correctly returns a promise obj.
Thanks,Nk
You really need to study up on Async behavior and callbacks, then take on understanding promises, as your examples are an odd combination of callbacks and promises, but, to try and explain what is going on in basic terms:
Example 1:
You always seeing KO first, because the first example does this:
Assign a function to a property that will be called back later
Show a KO alert
At some time later the file loads, starts the executor, which on complete (if it ever does) alerts OK
so, basically your onload function will only get called after the file loads (asynchronously), so the alert on the next line gets executed immediately.
Example 2:
You second example, in a comment, is this:
$.when(reader.onload = function (e) {
contents = reader.result;
return loadRequestExecutor();
}).done(function (a) {
alert("ok");
});
alert("KO");
Which translates to:
Assign a function to a property that will be called back later
Pass that same function to when but do not execute it!!!
Show a KO alert
At some time later when the file loads, return the loadRequestExecutor() to the filereader!!!
The end result is not returning the promise to the wait, which is what you probably meant, so it will never work as expected.
Suggestion:
I do not know the plugins that well, but you appear to need to record a promise relating to the load request executor, if that is what you want to wait for.
// Create the loadRequestExecutor and record the promise
var addAttchCallBack = loadRequestExecutor();
// Setup the onload callback
reader.onload = function (e) {
contents = reader.result;
alert("ok - file load is done");
};
// Listen for the loadRequestExecutor to complete
addAttchCallBack.done(function (data) {
alert("Ko - loadRequestExecutor is done");
})
alert("I am just an alert that will happen first, as everything above is asynchronous!");
Your overall aim is not clear from the question, so this answer mainly focuses on exampling why your two attempts do not work as you expected.
I have one function using to get data from text file and alert it in another function.
var library_name; // Global Variable
function getLibraryName(){
jQuery.get('stream.txt', function(data) {
library_name = data.toString().substring(17,data.length);
});
}
function saveFeedback() {
alert(library_name);
}
When saveFeedback is called, it will alert library_name
I have been tried to put it in the same function like this
function saveFeedback() {
jQuery.get('stream.txt', function(data) {
library_name = data.toString().substring(17,data.length);
});
alert(library_name);
}
but it is still keep saying undefined in console
How to solve this out? Without using parameter because saveFeedback function has to be called from somewhere else.
The second parameter to .get is called when the get finishes. You're saying, "fetch stream.txt and when it finishes, execute this function". The following calls saveFeedback when the get is finished:
function getLibraryName(){
jQuery.get('stream.txt', function(data) {
library_name = data.toString().substring(17,data.length);
saveFeedback();
});
}
Because get is asynchronous, your interpreter will instantiate the saveFeedback function before the success function is called (although some sanity checkers like JSLint probably want you to define saveFeedback before getLibraryName.
You shoud use saveFeedback() function in $.get(data) callback, because it it async request and you do not know, when it will be completed.
You can make a hidden input field and attach data to it using $.data();
For example:
function getLibraryName(){
jQuery.get('stream.txt', function(data) {
var library_name = data.toString().substring(17,data.length);
$('#myHiddenField').data('library_name', library_name);
});
}
function saveFeedback() {
alert($('#myHiddenField').data('library_name'));
}
jQuery get initiates an asynchronous call. Asynchronous means that the result from it will return later... maybe a short time later, maybe many seconds later. After kicking off this call, the code then proceeds immediately to the next line which is your alert. This alert occurs before the return from the asynchronous call, so of course the variable is still undefined--it hasn't been set yet.
One way to solve the problem might be to tell jQuery to make the call synchronous. But this is the wrong answer because it will stop the browser from responding to user interaction while the call is occurring. Instead, you need to adjust how you think about asynchronous calls. The basic concept is that instead of having a big function that does things step by step like a normal, procedural recipe (do step 1, then step 2, then step 3), instead you have to set up two different recipes or pieces of code: one to initiate the ajax call and then exit, and one to respond to the result of the ajax call.
Now, you already have two functions. You can't combine them for the reasons I already explained. But, you can chain them, or encapsulate one inside the other:
var library_name;
function saveFeedback() {
alert(library_name);
}
function getLibraryName(){
jQuery.get('stream.txt', function(data) {
library_name = data.toString().substring(17 ,data.length);
saveFeedback(); // this chains the two functions together
});
}
or maybe even better:
var library_name;
function saveFeedback() {
alert(library_name);
}
function receiveLibraryName(data) {
library_name = data.toString().substring(17, data.length);
saveFeedback();
// additional statements here after saving
}
function getLibraryName(){
jQuery.get('stream.txt', receiveLibraryName);
}
The point is that you cannot continue in the next statement as usual within the getLibraryName function. The steps you wish to take after the ajax call must be inside of another function: either in the callback function itself, or in another function called from the callback function.
Try following code:
var library_name;
function getLibraryName(){
jQuery.get('stream.txt', function(data) {
let lbName= data.toString().substring(17,data.length);
saveFeedback(lbName);
});
}
function saveFeedback(lbName) {
library_name = lbName; //If you are using library_name in other code
alert(library_name);
}
You have to define library_name before jquery.get once. Because if the jquery.get doesnt work library_name will not be created by the time u call alert.
please add
var library_name;
as the first line of saveFeedback().
I'm having issues getting a variable declared in an .click function to be updated in a Get function within the click function. I've gathered that even though the variable has the same name, within the Get function it is really declaring it anew.
I've tried to find examples helping me, but it appears to me that the Get method is such a specialized function that the examples didn't seem to apply.
I would like the value of 'SettingContentToEdit' to get updated with information retrieved with the Get function.
Below is the code.
Thank you for your help!
$(".cellSetting").click(function () {
var clickedClass = $(this).attr("class");
var clickedItemID = $(this).attr("id")
var SettingContentToEdit = "not changed";
var JSONSend = {
'ItemName': clickedItemID, //send the item name so the model knows which one to pull up!
'ItemSetting': clickedClass
};
$.get(
'/Home/getItem',
JSONSend,
function (data) {
// $('#dialog').html(data.ItemSettings[data.SettingToEdit]);
SettingContentToEdit = data.ItemSettings[data.SettingToEdit];
alert(SettingContentToEdit); //returns the correct info
}
);
alert(SettingContentToEdit); //returns "not changed"
});
Your issue is that your ajax call is asyncronous. The success handler for the get() function is called some time after your click handler and the alert() has already completed. You can refer to the local variables in your success handler, but the code that follows the success handler executes BEFORE the success handler does.
This is because your get() operate is asynchronous. Calling it just STARTS the networking operation and then your javascript execution continues (while the networking operation works in the background). After starting the networking operation, your alert() is called. Then, some time LATER, the Ajax call completes and the success handler is executed.
This is a very common mistake and has indeed been asked and answered hundreds (if not thousands) of times here on SO (I've personally probably answered 20-30) so you are not alone in missing this understanding at first.
If you want to use the results of the ajax operation, then you need to put the code that does that either in your success handler or put it in a function that you call from your success handler. You cannot put it after the get() function because it will execute too soon before the results are known.
AJAX is asynchronous. If you check SettingContentToEdit a second or so later than you are doing, you'd see the value has updated.
Either put your code inside the get function (where you have your alert showing the correct value) or make the request synchronous (you'll have to look up the jQuery docs because I don't use jQuery).
I have a problem returning a variable in my function, the below script works fine:
function sessionStatus(){
$(document).ready(function(){
$.getJSON(scriptRoot+"sessionStatus.php",function(status){
alert(status);
});
});
}
sessionStatus();
Bet when I try the following I get a message box with the message "undefined":
function sessionStatus(){
$(document).ready(function(){
$.getJSON(scriptRoot+"sessionStatus.php",function(status){
return status;
});
});
}
alert(sessionStatus());
This is really bugging me, I just can't seem to see what I've done wrong.
There are two things you should know:
1: the JSON thing is asynchronous, so the function call to sessionStatus could already be done when the JSON is still being fetched. The following would work:
function sessionStatus(callback){
$(document).ready(function(){
$.getJSON(scriptRoot + "sessionStatus.php", function(status){
callback(status);
});
});
}
sessionStatus(function(s){alert(s);});
or rather:
function sessionStatus(callback){
$(document).ready(function(){
$.getJSON(scriptRoot + "sessionStatus.php", callback);
});
}
sessionStatus(function(s){alert(s);});
2: even when it would be synchronous, you are only giving a return value from the inner function, so the sessionStatus would return nothing. Check out this code (not related to your JSON thing):
function do() {
var x = 0;
(function(){
x = 2;
})();
return x;
}
or:
function do() {
var x = (function(){
return 2;
})();
return x;
}
Both return 2. Hopefully this explains a bit.
Your function sessionStatus() doesn't return anything, hence the alert says undefined.
All the function does is set thing up for the AJAX call to happen once the page loads - nothing actually happens within sessionStatus() that could be returned.
The code in function(status) { ...} doesn't get run until the AJAX call to the server returns a value, and that AJAX call doesn't get sent until the page loads.
You ought to read up on what $.getJSON() and $(document).ready() actually do, because you're going to continue to get confusing behaviour until you understand them properly.
Your sessionStatus() function never returns anything. It sets a function to run later, and that function returns something, but that's not anything to do with sessionStatus()
You're returning a value when the document ready event is done. Where is your value supposed to go? The jQuery object doesn't know what to do with it.
The function sessionStatus just sets up the event listener for $(document).ready() and then returns without returning a value. That's the undefined you see.
Later when $(document).ready() fires it calls the ajax which if it succeeds returns the status, but nothing is receiving that status.
function sessionStatusCallback(status)
{
alert(status);
}
function sessionStatus(){
$(document).ready(function(){
$.getJSON(scriptRoot+"sessionStatus.php",function(status){
sessionStatusCallback(status);
});
});
}
sessionStatus();
Your function is being called asynchronously -- actually after two asynchronous calls, made via .ready() and .getJSON(). In such a case there is no available return value, instead you have to use a callback, as in the above, to process the response.
Though I should note that the function passed to getJSON in the above already is a callback. You could change that function definition to just be "sessionStatusCallback" and it would call the above callback once the JSON was ready, and you could continue to process there. Or...continue your processing in the current callback (it's a matter of style whether to use a function reference or declare the anonymous function right there in the .getJSON() call)
Functions should never be included in a jQuery(document).ready function. Separate them, so you don´t have side effects you don´t want to have. How do you want to call the session status? And witch function should get the return value?