1

I need to grab the variable prodata from this function (which is populated dynamically), in order to use it in another function. But I don't know I can use return. Where to put return so that I can use prodata outside of this function.

$.get("proDB.txt", function(data) {
    var lines=data.split(/\n/);
    var numberofmodels=lines.length-2;
    var prodata=[];
    var i;
    var fieldnames=lines[0].split(/\t/);
    for (i = 1; i < lines.length-1; ++i) {
        var fields=lines[i].split(/\t/);
        var j;
        prodata[i]={};
        for (j = 0; j < fields.length; ++j) {
            prodata[i][fieldnames[j]]=fields[j];
        }
    }
    //remplir la liste déroulante:
    var options = '';
    for (i = 1; i < lines.length-1; ++i) {
        if (prodata[i]['name'].indexOf("elly") >= 0) {
            options += '<option value="' + prodata[i]['id'] + '" selected>' + prodata[i]['name']+', '+prodata[i]['brand']+', '+prodata[i]['model']+'</option>';
        }else{
            options += '<option value="' + prodata[i]['id'] + '">' + prodata[i]['name']+', '+prodata[i]['brand']+', '+prodata[i]['model']+'</option>';
        }
    }
$("#userchosenpromodel").html(options);
}, 'text'); //$.get

and then I need to access and use prodata within

$('#submitbutton').click(function(e) {
    e.preventDefault(); 
    //computeUserDimensions(prodata[proId]);
});

function computeUserDimensions(line){
Ingo Karkat
  • 167,457
  • 16
  • 250
  • 324
Louis
  • 2,548
  • 10
  • 63
  • 120
  • $.get() is asynchronous, so there's no way to return a value from it. You'll need to utilize the variable from somewhere within your $.get() callback. – jmar777 Apr 04 '13 at 19:59
  • 2
    You can't return the value outside as the execution is asynchronous, you have to use the variable in the callback or in a function you call from the callback. – Denys Séguret Apr 04 '13 at 19:59
  • how to use the variable in a function I call from the callback, can you give an example? – Louis Apr 04 '13 at 20:04
  • or maybe I can read my file differently? – Louis Apr 04 '13 at 20:05

3 Answers3

2

You can't use it outside of that function, otherwise it will get used before it exists. An alternative is to use deferred objects.

var request = $.get("myurl",handler,"text");

Now, if you need to get at the data from handler, just use this:

request.done(function(data){
    // use the data here, but not outside
    console.log(data)
});

One way around this to keep your work in the handler but allow you to get the modified var is to store a reference to it outside, and only access it within a .done().

var prdata;
var request = $.get("myurl",function(data){
    prdata = data;
},"text");
console.log(prdata); // undefined because request isn't done
request.done(function(){
    console.log(prdata); // IS defined because request IS done
});
console.log(prdata); // undefined because request still isn't done
Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • I am a newbie! CAn you please develop your advice for my example? I don't know what to do with `handler`... – Louis Apr 04 '13 at 20:08
  • `handler` is your existing code, `function(data) {...` – Kevin B Apr 04 '13 at 20:09
  • @user130482 `handler` is the function that can access the AJAX call response. You can't return the response from your function. – John Dvorak Apr 04 '13 at 20:09
  • ok thanks. The variable I need to use outside is `prodata`, not `data` – Louis Apr 04 '13 at 20:10
  • @user130482 you can't get it outside. you can't get data outside either. – Kevin B Apr 04 '13 at 20:11
  • then I'll use your way and get through request.done... is prodata available in there? – Louis Apr 04 '13 at 20:12
  • I need to use prodata in a another function a little bit lower in my file : `$('#submitbutton').click(function(e) {...}`....I guess it is not possible. Can you advise on how to restructure all that so I can do what i need? – Louis Apr 04 '13 at 20:14
  • The answer from Dustin did the trick. Thanks for your help. – Louis Apr 04 '13 at 20:18
  • @user130482 I strongly suggest against using `async: false`. It can and will cause a bad user experience when the server or network hangs for a second+. While a synchronous request is being sent, the browser is locked up until it completes. You won't notice this when working locally from the server because your network speed is near instant. – Kevin B Apr 04 '13 at 20:20
  • Ok I see, thanks @Kevin B, what do you suggest then? I would need a function that reads my text file and returns this array `prodata`from it. Even better would to move this function to my other js file: function.js – Louis Apr 05 '13 at 07:37
  • I am gonna test what you edited in your answer. I'll get back to you. Thanks for your help. – Louis Apr 05 '13 at 08:29
  • I am testing your new suggestion: The problem is that I need to access prodata from within `$('#submitbutton').click(function(e) {...});` How can I pass `request` into this? – Louis Apr 05 '13 at 09:19
  • Actually thinks are clearer: there are two issues here. 1: I need to populate prodata[] dynamically as you can see line 11 of my example. and 2: I need to be accessible from within another function. I am editing my question to make it clear. – Louis Apr 05 '13 at 10:18
  • @user130482 Have i not made it clear enough that you CAN'T do that? – Kevin B Apr 05 '13 at 14:08
  • Ok that works. But now it led to another problem regarding the event that I ask here: http://stackoverflow.com/questions/15837179/jquery-global-variables-usable-everywhere – Louis Apr 05 '13 at 19:27
0

Another option would be to make prodata global, as before, but disable to submit button until it has been populated. Something like this:

// Declare prodata here
var prodata = [];

// Disable submitbutton so it won't be clicked before prodata is ready
$('#submitbutton').attr("disabled", "disabled");

$.get("proDB.txt", function(data) {
    var lines=data.split(/\n/);
    var numberofmodels=lines.length-2;
    var i;
    var fieldnames=lines[0].split(/\t/);
    for (i = 1; i < lines.length-1; ++i) {
        var fields=lines[i].split(/\t/);
        var j;
        prodata[i]={};
        for (j = 0; j < fields.length; ++j) {
            prodata[i][fieldnames[j]]=fields[j];
        }
    }
    //remplir la liste déroulante:
    var options = '';
    for (i = 1; i < lines.length-1; ++i) {
        if (prodata[i]['name'].indexOf("elly") >= 0) {
            options += '<option value="' + prodata[i]['id'] + '" selected>' + prodata[i]['name']+', '+prodata[i]['brand']+', '+prodata[i]['model']+'</option>';
        }else{
            options += '<option value="' + prodata[i]['id'] + '">' + prodata[i]['name']+', '+prodata[i]['brand']+', '+prodata[i]['model']+'</option>';
        }
    }
    $("#userchosenpromodel").html(options);

    // Enable submitbutton since prodata is now available
    $('#submitbutton').removeAttr("disabled");
}, 'text'); //$.get

$('#submitbutton').click(function(e) {
    e.preventDefault(); 

    // Do an if check here just in case we somehow got here when prodata wasn't ready
    if ( prodata.length > 0 ) computeUserDimensions(prodata[proId]);
});

function computeUserDimensions(line){}

This will allow you to access prodata from your click method, because the click method will never be accessed before prodata is available.

Dustin Wilhelmi
  • 1,769
  • 2
  • 13
  • 27
-1

As others have pointed out, it gets problematic using the variable outside of the callback due to the asynchronous nature of the $.get call. However, if you need to, you can make the call synchronous. In order to do that, you have to use the more generic $.ajax instead of $.get, and pass it async:false, and you need to define prodata above the ajax call:

var prodata=[];
$.ajax({
  url: 'proDB.txt',
  async: false,
  dataType: 'text',
  success: function(data) {
      // do stuff to prodata here
  }
});
// use prodata here
Dustin Wilhelmi
  • 1,769
  • 2
  • 13
  • 27