3

I created a function that makes a jquery AJAX call that returns a JSON string. On its own, it works fine -- and I can see the JSON string output when I output the string to the console (console.log).

function getJSONCustomers()
{
var response =  $.ajax({
    type: "GET",
    url: "getCustomers.php",
    dataType: "json",
    async: false,
    cache: false
  }).responseText;
  return response;  
};

However, when I set a variable to contain the output of that function call:

var mydata = getJSONCustomers();

, then try to use it within my Twitter-Bootstrap TypeAhead function (autocomplete for forms):

data = mydata;
console.log(data);

I get an 'undefined' error in my console.

Below is a snippet of this code:

$(document).ready(function() {

var mydata = getJSONCustomers();

$('#Customer').typeahead({
    source: function (query, process) {
        customers = [];
        map = {};

        data = mydata;
        console.log(data);

 // multiple .typeahead functions follow......
});

Interesting here, is that if I set the data variable to be the hardcoded JSON string returned from the AJAX function, everything works fine:

data = [{"CustNameShort": "CUS1", "CustNameLong": "Customer One"}]

How can I use the JSON string within my typeahead function?

tresstylez
  • 1,809
  • 6
  • 29
  • 41
  • I think this has to do with synchronous code, but I'm not sure. Where did the original (working) `console.log` go? – Alfred Xing Jul 08 '13 at 17:55
  • I can call var mydata = getJSONCustomers(); -- then immediately do a console.log(mydata) and it works fine. It's only after i'm within the typeahead block that it stops working. – tresstylez Jul 08 '13 at 18:00
  • "if I set the data variable to be the hardcoded JSON string" - you don't. You assign an array containing one object to it. – a better oliver Jul 08 '13 at 18:03
  • @tresstylez To clarify further, does manually setting `data` to `'[{"CustNameShort": "CUS1", "CustNameLong": "Customer One"}]'` (a JSON string) work, as in your last comment? – Alfred Xing Jul 08 '13 at 18:06
  • @AlfredXing - No. It does not work when the JSON string is within quotes: `data = '[{"CustNameShort": "CUS1", "CustNameLong": "Customer One"}]'`. It only works like this: `data = [{"CustNameShort": "CUS1", "CustNameLong": "Customer One"}]` – tresstylez Jul 08 '13 at 18:13
  • It's like Alfred Xing said, it's an Ajax issue. The variable ```mydata``` used inside the typeahead initialisation code is undefined, because the Ajax call is not yet complete at this point in time. – Dzulqarnain Nasir Jul 08 '13 at 18:16
  • Right, so that is my question :) How can I use the mydata data within the typeahead? – tresstylez Jul 08 '13 at 18:29
  • 1
    `.responseText` returns a **string**. You have to parse the string first: `var mydata = JSON.parse(getJSONCustomers());`. That being said, you should avoid making synchronous calls. Have a look at http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call. – Felix Kling Jul 08 '13 at 18:40
  • @FelixKling - Your JSON.parse of the function response resolved my issue. Submit an official 'answer' and I'll give you credit! Thanks everyone for the suggestions. – tresstylez Jul 08 '13 at 19:00

2 Answers2

8

.responseText returns a string. You have to parse the string first to be able to work with the array:

var mydata = JSON.parse(getJSONCustomers());

That being said, you should avoid making synchronous calls. Have a look at How do I return the response from an asynchronous call? to get an idea about how to work with callbacks/promises.

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
0

The problem is that the Ajax request hasn't had the chance to complete before typeahead is initialised, so typeahead is initialised with an uninitialised mydata variable. Also, as of jQuery 1.8+ async: false has been deprecated and you need to use the complete/success/error callbacks.

Try this:

function getJSONCustomers(callback) {
    $.ajax({
        type: "GET",
        url: "getCustomers.php",
        dataType: "json",
        cache: false,
        success: callback
    });
};

And then you could do something like:

getJSONCustomers(function(mydata) {
    // mydata contains data retrieved by the getJSONCustomers code
    $('#Customer').typeahead({
        source: function (query, process) {
            customers = [];
            map = {};
            console.log(mydata);

 // multiple .typeahead functions follow......
    });
});

So your code completes the Ajax call before initialising the typeahead plugin.

Dzulqarnain Nasir
  • 2,150
  • 1
  • 19
  • 16