How to access global variable

I have a global variable I intend to alter from inside an AJAX callback but I haven’t had much luck with it. I’ve tried accessing it through the window object but when I console log the variable from within that callback, it logs the changes meaning the variable was perceived as coming from the local scope. I’ve also tried declaring it specifically with the var keyword but that doesn’t work. How do I get around it? My code below

var error = false, postSuccess = false, replace;
function post () {
	$.post('new_comment.php', {new_comment: typedText, parent_post: thisPost}, function(e) {
	window.postSuccess = true;
}

function loadingComment () {
		post ();
		if (postSuccess == true) {
			console.log("post just ran", postSuccess); // Logs false
}

The reason why this doesn’t work (apart from all the missing brackets) is that the AJAX callback gets executed when the success-response arrived, which will most certainly be after you checked postsuccess == true. Remember, the first A in AJAX means “asynchronous”! Try this:

$.post(
  'new_comment.php', 
  {new_comment: typedText, parent_post: thisPost}, 
  function(e) {
	console.log('foo');
  }
);
console.log('bar');

and note that “bar” will be logged before “foo”; the AJAX call won’t halt your program until the callback gets executed. So if you want to execute code after a successful response, you’ll have to put it into the callback function (or call it from there) – that’s what the callback is for, after all. :-)

PS: If you do want to halt your program until the response arrived, you might use jQuery’s $.ajax() method, which provides a way to perform the request synchronously IIRC. However this is not a particularly good idea since you don’t know when – and if – the server will respond, so it might just keep hanging.

LOL!! Bro this is a snippet carved out from a mightier chunk of code or you think I have a script that simply alters a solo variable? I was bound to miss a thing or two. But thanks for stopping by all the same :slight_smile: .

For everyone that might stumble on this thread in search of help, I think I just found the mother lode as regards asynchronity triggered by synchronity. It’s so weird I can’t even find a proper title for it but all the same, you should find [this] (http://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) quite helpful.

You need to get rid of that as global variables in JavaScript are very bad (unless you are referring to the one variable needed to pass a library such as jQuery into the script tht you have written that uses it - the only reason for using any global variables at all in JavaScript).

By this, you mean if I have written a library or plugin? I’m a bit confused. Also, this is the very first time I’m learning global variables are bad. For one, they improve readability and encourage DRY for vars that would be used repeatedly in several functions. I tend to declare all variables I need on the first line of my script and functions subsequently except variables only available at runtime. You’d shoot me where you the window object or JavaScript engine.

One of the large dangers of global variables is that they can be easily clobbered by other code.

For example, if you have some code that sets a global variable then later on uses it, you will face unexpected problems when adding other library code, that can be tricky to diagnose.

A simple example is:

var message = "";

message = "Executed first, responded last.";
setTimeout(function () {
    console.log(message);
}, 0);

You expect “Executed first, responded last.”, but instead, what you get on the console is:

    Tim's amazing library
    Tim's amazing library

because Tim’s library had a certain side-effect.

message = "Tim's amazing library"
console.log(message);

A safer way is to use an immediately-invoked function expression, called an IIFE. That protects the global namespace from your code, and helps to ensure that other code cannot interact badly with your own.

The following code works perfectly fine, no matter what other side-effects are attempted from other code:

(function () {
    var message = "";

    message = "Executed first, responded last.";
    setTimeout(function () {
        console.log(message);
    }, 0);
}());

Even with Tim’s library going, you now get your expected logged output, because your message variable is protected by the IIFE:

    Tim's amazing library
    Executed first, responded last.

Avoid globals like the plague. Protect your code by wrapping it in the IIFE condom.

2 Likes

Definitely the way to code ALL JavaScript.

As I mentioned before the ONLY time you need global variables in JavaScript is when you are using a library. For example with jQuery you need a single global variable called “jquery” to pass into your IIFE in order to provide access to the library

jQuery.noConflict();
(function($) {
   // jQuery code goes here
}(jQuery));

with that the $ references inside the IIFE refer to jQuery while those in another IIFEcan be referring to something completely different - only the “jquery” variable itself is global so as to allow your IIFE access to that library.

Why then does the noConflict method get called in the global scope instead of inside the defining IIFE? Second question is, the jQuery supplied as argument I understand is an object. How does it exist independent of the IIFE which should be its home or is the object coming from another script?

Lastly, what is the significance of the noConflict method or did you just pick it randomly?

It stops jQuery creating $ as an alias of the jQuery variable. By placing it in global scope it stops jQuery creating an unneeded global variable and frees that variable up for use by other libraries that you might be using in a different IIFE.

Without that line jQuery puts two variables in global scope where it only needs one.

For others that want to know the details, it doesn’t stop jQuery from creating the $ variable, as jQuery has already taken over the $ variable before the noConflict is used. What noConflict does is to return the $ variable back to what it was before jQuery took it over.

There is also no difference with the noConflict being inside or outside of the IIFE. This code example will work as well:

(function($) {
    jQuery.noConflict();
    // jQuery code goes here
}(jQuery));

The reason why it’s not done though is that it can be misunderstood. You don’t want people to gain the false impression that the noConflict is restricted within the IIFE. It has a global consequence, so it’s best to leave it global outside of the IIFE.

2 Likes

You sound like a contributor to the jQuery library. How do I read the code and understand it like you have when the variables used inside it are single alphabets that mean very different things inside the various objects containing similarly alphabets but point to the different properties that make up the library?

I am not. I have never actually used jQuery beyond working out what the equivalent jQuery commands are to the various native JavaScript commands.

1 Like

That’s the minified version of the code. There is also the normal uncompressed jQuery which is easier to understand, but perhaps even better is to have a read through the annotated source code which gives even more details.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.