-2

I'm trying to pass data that I've received from a JSON file to a later point in my code. This is the part that receives the JSON data:

function getLeft(x){
    var result
    $.get('info.json',{},function(data){
        result = data.doors[x].left;
        console.log(result);
        return result;
    });
}

and this is the part that uses it:

if(getLeft(0) == true){
     alert("door is locked");
}

Through debugging I know that result from the getLeft function is returning the correct data, but actually checking the data of getLeft(0) comes out as undefined. I've googled this, but I'm still really confused about why it does this, or how to fix it. I'm really new to jQuery and Javascript so any help would be greatly appreciated.

Josephine
  • 261
  • 2
  • 10
  • 20
  • read up on what AJAX stands for and pay close attention to the first `A`. This question gets asked here daily – charlietfl Nov 03 '13 at 23:10
  • @charlietfl, good point, but FYI the acronym AJAX can't be taken literally. Most people do AJAJ (JSON instead of XML). But most people still refer to it as AJAX. So if someone took the whole AJAX acronym literally, they may have misconceptions. – Paul Draper Nov 04 '13 at 03:54
  • @PaulDraper wondered myself why the X a while ago also.... since `AJAX` is the first line item in nav of jQuery API...really doesn't fall on us to rename it – charlietfl Nov 04 '13 at 04:13

4 Answers4

0

This does not work because getLeft() doesn't return anything. The ajax call is fired asynchronosouly and your return statement in the callback returns from the callback context.

nietonfir
  • 4,797
  • 6
  • 31
  • 43
0

You can't do such a thing.

The return statement, as you wrote it, is not related to the outer function "getLeft", but to the inner callback function.

Ajax is asyncronous by default, so you have to wait the callback to be called to have the results, you can't return that directly.

ProGM
  • 6,949
  • 4
  • 33
  • 52
0

The $.get call is asynchronous, since a request over the Internet could take a long time.

A quick fix is to make is synchronous.

function getLeft(x){
    var result;
    $.ajax('info.json',{async:false, success:function(data){
        result = data.doors[x].left;
        console.log(result);
    }});
    return result;
}

Though do read up about asynchronous handling. It does take some getting used to, but it is better practice.

EDIT: example: http://jsfiddle.net/bL4Aj/

Paul Draper
  • 78,542
  • 46
  • 206
  • 285
  • 1
    using async false i just plain bad practice – charlietfl Nov 03 '13 at 23:14
  • Why the silent downvotes? This answer is 100% correct, and this is the only answer which shows a fix to the OP's code. – Paul Draper Nov 03 '13 at 23:14
  • but it's deprecated and there are certainly alternatives to blocking the browser – charlietfl Nov 03 '13 at 23:15
  • 1
    @charlietfl, async is NOT deprecated. https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest http://www.w3.org/TR/XMLHttpRequest/ – Paul Draper Nov 03 '13 at 23:17
  • @nietonfir, then why the JSFiddle work? – Paul Draper Nov 03 '13 at 23:33
  • Read my comment edit please. I overread that you suggest to use `async: false` (which is just wrong because it locks the current thread - completely). You should read http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call – nietonfir Nov 03 '13 at 23:36
  • @charlietfl if you actually read the jQuery docs, you'd know that `async: false` is *only* deprecated for use with the `jqXHR` (`$.Deferred`) object. `$.ajax` (and `$.get`) returns a `jqXHR` object with functions such as `done` on it. You shouldn't use those if you use async: false. And it's fine if you don't like the synchronous XHR calls, but I chose to answer the OP question as it was, and not as I wanted it to be, and to follow JavaScript standards and real documentation. – Paul Draper Nov 03 '13 at 23:37
  • since it blocks UI...and I spent a long time around jQuery forum....it's been suggested for 4-5 years not to use there. Is bad practice in my book and most around here as well. Why try to use it if it works only if you don't use promise then try to debug people using it incorrectly...especially when there are simple ways around it – charlietfl Nov 03 '13 at 23:40
  • @nietonfir and charlietfl, I know it blocks the thread (you called it the UI thread, but there is only one, whatever you call it). what the hell do you think synchronous means? There are advantages to using async (hence, it being in the standard, and being implemented by every single browser in the history of the earth), and there are disadvantages. In the very first version of my answer, *I said* it was better practice to set up the program asynchronously. – Paul Draper Nov 03 '13 at 23:45
  • @PaulDraper understand you are frustrated... perhaps you've used asynch quite a bit.... but from best practices point of view in jQuery community it's frowned on. Personally I've never used it, not that I'm a wizard...just learned from being around jQuery forum since about 2008 how not to need it and seeing headaches peole ran into who did. I believe it ws slated for a full deprecate as longg as about 2 years ago...around 1.6-1.7 – charlietfl Nov 03 '13 at 23:51
  • @charlietfl, asynchronous certainly is the best practice (in JavaScript and many other languages). So I gave two solutions in my answer. One was the simple solution; one was the best practices solution. This is very common on SO. If my answer did not deserve an upvote so be it, but it was not off-topic, nor misleading, nor containing misinformation. Notice that the only answer with an upvote has the `async:false` solution (but much worse...globally). – Paul Draper Nov 04 '13 at 03:50
0

add this instruction before your code :

$.ajaxSetup({
async: false
});

since ajax call should be in this situation.

And you should modify your code as following :

function getLeft(x){
    var result
    $.get('info.json',{},function(data){
        result = data.doors[x].left;
        console.log(result);

    });
   // Return statement here and not in ajax call
   return  result;
}

UPDATE :

Another methodology is to use Hook pattern to avoid the pb of synchronicity:

  function getLeft(x,callbk){
        $.get('info.json',{},function(data){
            if(typeof callbk=='function'){
                callbk.call(this,x, data.doors[x].left)
             }  

        });
  }

Known that callbk argument is the name of a function :

 function myFn(x,result){
          if(x==0 && result){
            alert("door is locked");
          }
 }

Example :

   getLeft(0,myFn)
Abdennour TOUMI
  • 87,526
  • 38
  • 249
  • 254
  • 1
    I DO NOT recommend put that in `ajaxSetup`. It will make all calls synchronous. Instead just put it on the call itself (see my answer). – Paul Draper Nov 03 '13 at 23:40