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?
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 have to call two functions on form submit but i want to make sure that that second function is executed only after the first function is executed.
I do not have control over the first function, so i cannot edit it at all.
function a(et){
//function a script
}
function b(evt){
//function b script
}
from function b is there a way that i can check if function a was completed or executed fully.
if you have no access to a at all then you can't do what you want to do here. No way: JS creates a call object when a function is called, and auto-GC's it when the call is complete. Sadly, the actual mem-management is off limits, so you can't check that. other trickery involves your meddling with the code of function a, which you say you cant get at... so no, you can't do this.
Sorry for that, but it's as the FAQ says: you might not always get the answer you're hoping for, but that doesn't mean the answer you don't like isn't true... :-P
There is, however, a little bit of hope for you: if both function a and b are callbacks or handlers of a submit event, you could look into ways of queueing those calls. Given the jQuery tag .queue() suggests itself
According to Eli Grey you can tested like this:
function foo() {
foo.complete = false;
// your code here
foo.complete = true;
}
foo.complete = false;
if (foo.complete) { // foo execution complete
// your code here
}
Yes, you can, there is a lot of ways to do that, but here is a simple way to make it.
You can use persistent object localStorage.
You can use session object sessionStorage.
function a(evt){
// Asynchronous function
// ... your code here
// before finish function create the persistent object
localStorage.setItem('myObject', 'done');
return;
}
function b(evt){
// Checks if a() function was completed
var _done = localStorage.getItem('myObject');
if(_done && _done == 'done') {
// your code here: the a() function was completed
localStorage.removeItem('myObject');
}
}
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've this function
function getTags(level){
$.getJSON("php/get-tags.php", { "parent": level }, function(json) {
return json;
});
}
I'm calling this function as
$(function(){
var tags = getTags('0');
});
The problems is, in the function getTags() the return json is like
{"tags":["Mathematics","Science","Arts","Engineering","Law","Design"]}
but at var tags = getTags('0'), catching the return value, it gets an undefined value.
Is the way I'm returning the value incorrect?
Like many others already correctly described, the ajax request runs asynchronous by default. So you need to deal with it in a proper way. What you can do, is to return the jXHR object which is also composed with jQuery promise maker. That could looke like
function getTags(level){
return $.getJSON("php/get-tags.php", { "parent": level });
}
and then deal with it like
$(function(){
getTags('0').done(function(json) {
// do something with json
});
});
getJSON is asynchronous, the function that called it will have finished by the time the HTTP response gets back and triggers the callback.
You cannot return from it.
Use the callback to do whatever you want to do with the data.
You are trying to call an asynchronous function in a synchronous fashion.
When you call getTags, the it triggers a call to your PHP page, if javascript was blocking, then your page would hang until your server responded with the JSON. You need to re-think your logic and trigger a callback.
function getTags(level){
$.getJSON("php/get-tags.php", { "parent": level }, function(json) {
//do something with the JSON here.
});
}
You cannot return from an AJAX call. It's asynchronous. You need to have all logic dealing with the returned data in the callback.
If you need it to work like that, your getTagsfunction must return a value. It does not at the moment. You could achieve this by using $.ajax and setting async to false.