4

I have difficulty understanding how a javascript callback should work. I am using the following code to get values from a MySQL database:

  $.post("getResults.php", { x: 100, y: 200},       
   function(arrayOfValues){  
      alert( arrayOfValues[2] )         
   }, 'json');

alert() returns the correct value, and is functioning as expected. However, I don't understand how the value from arrayData[2] can be passed or returned to other parts of my program (and attempts I've made have not worked).

I've read through the jquery help and numerous SO questions and answers but I don't understand how a callback works.

In this case, I want arrayOfValues[2] to be accessible by my main program.

djq
  • 14,810
  • 45
  • 122
  • 157
  • 1
    I've realized that the problem is due to the length of time it takes for me to get the data. Is there anyway I can have my program wait until it receives the POST data before moving on to the next part? – djq Jan 17 '11 at 02:36

4 Answers4

2

The $.post() is asynchronous (non-blocking) call, which means that the function returns immediately (does not wait for server response) and next javascript code is executed. When response from the server arrives, your callback function is called, with the response...

Let's say, you want to display the content in a div:

$.post('url.php', {}, function(content) {
  $('#div_id').html(content);
});

// or shorter:
$('#div_id').load('url.php', {});

Or you can have an object with some logic and register object's method as a callback:

function MyHandler(msgElement) {
  var sum = 0;
  this.onSuccess = function(content) {
    sum = sum + content[0];
    if (sum > 100) {
      msgElement.html('Sum has reached 100 !');
    }
  };
  this.otherMethod = function() {
    alert('Current sum is:' + sum);
  };
}

var handler = new MyHandler($('#my_div'));

// do the request
$.post('url.php', {}, handler.onSuccess, 'json');

// you can call any method of handler object using global variable handler
// or passing a reference (handler object) to any other object
// notice, if you call this method immediately after sending the request,
// the sum var is likely to be 0, as the response has not arrived yet...
handler.otherMethod();

Basically, you have many options. So if you need more info, specify what exactly you wanna do the response...

Vojta
  • 23,061
  • 5
  • 49
  • 46
  • Thank you for your answer. What I am trying to do is to set the array `arrayData` to a value that I can access later in my javascript. So if I write `this.onSuccess = function(arrayData){a = arrayData[2]; return x }` can I then access `x` elsewhere? – djq Jan 17 '11 at 00:49
  • The callback (`this.onSuccess` function) is called by browser, when response arrives, so it does not make a sense to return any value - you don't have access to it. Did you read my code ? The second example is doing, what you need - accessing `sum` variable through closure. Then, any other function method of this MyHandler could access this `sum` variable as well... Check out my updated answer, I have added `otherMethod` to show that... – Vojta Jan 17 '11 at 09:37
1
var foo;

$.post("getResults.php", { x: 100, y: 200 }, function(data) {  
    foo = data;       
}, 'json');

The response data will be stored into the foo variable. Note, however, that this is an asynchronous callback function which is called when the HTTP response arrives. It is important to understand that you cannot use the foo variable until that HTTP response has arrived and the callback function has finished.

Šime Vidas
  • 182,163
  • 62
  • 281
  • 385
  • How do I know when the response has arrived? I've realized that the root of my problem is using it, before the value has returned. – djq Jan 17 '11 at 02:28
  • @celenius Yes, I figured that that's your issue :) Well, the whole point of having an asynchronous function is being able to execute code in an unknown instant in the future. You don't know then the response is going to arrive, that's why you are using the asynchronous callback in the first place. With that being said, you now have multiple options. For example, you can delay your code via timeouts until the `foo` variable becomes populated. – Šime Vidas Jan 17 '11 at 02:38
  • hmmm. So if I structure it like this: ` $.ajax({ type:"POST",url: "getLatLongv2.php", data:{ latUser: latArrayVal, longUser: longArrayVal}, async: false, success: function(arrayData){ alert(arrayData[2]); arrayValue = arrayData[2];}, dataType:'json' });` would that be one approach? – djq Jan 17 '11 at 02:47
  • @celenius It depends really on what you are trying to do with the response data. Could you elaborate on that? – Šime Vidas Jan 17 '11 at 03:07
1

Callbacks, let me try and explain it in a way that you can understand.

  • Firstly you need to understand how a function can be assigned to a variable without being executed.

This allows you to pass around functions and only executed them when you want, heres an example how I can pass a function to a variable and not executing it:

a = function(){}

This is a small example and most common, you would call the function like a() adding the () tells the function to execute.

  • Now you should understand that you can pass these variables into another function, yet not calling them

the below example shows you how you can pass a function into the above function a whilst executing it.

b = function(){}
b(a);
  • the next step is to be able to create anonymous functions, these will allow you to assign a function to a variable whilst passing into another function

an anonymous function is not assigned at the point of writing it but is assigned when its parsed within the outer functions scope.

the above my be a little tricky to understand but hopefully the example will clear it up.

a(
    function(){}
);

The above is the same as the b(a) example apart from a is now an anonymous function, and is only assigned to the variable within b, i.e the outer function.

jQuer'ies API relies heavily on anonymous functions as there easy to use and create separation from the jQuery Core and the users code, the user does not need to heavily rely on the main code of jQuery but pass a callback to allow jQuery to connect to your code rather.

an example of a function that uses similar means of passing data in and out of functions are like so:

JoinUser = function(Firstname,Lastname,callback)
{
     Fullname = Firstname + " " + Lastname;
     callback(Fullname);
}

JoinUser("Robert","Pitt",function(Fullname)
{
    alert(Fullname); //Robert Pitt
})

the above example only shows you roughly how the style of jQuery works, but not the most important benefit of callbacks and that's Ajax.

Ajax can halt a javascript script until its data has been received, for example:

Result = RequestPage("Contacts");

when Ajax sees this line it has to wait for RequestPage to return the result because the coding further down is expected to require this value, so we have to wat for the data to be returned from the server before JavaScript continues, this can be several seconds and cause the UI To act abnormally.

The way we get around this is to send a callback to the function and tell it to call when its done as I want to work on the rest of the application.

RequestPage("Contacts",function(){});

so now the JavaScript continues down the page performing the task it needs, and within the RequestPage function it would be layed out like so:

function RequestPage(page,callback)
{
    //..
        request.oncomplete = callback;
    //..
}

This way the rest of your application has done other task and when the result is ready you can change the UI froim the result.

This is also why we use loaders to replicate a working state.

I hope you begin to understand how jQuery takes advantage of these factors of javaScript and it will help you to develop your application.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
RobertPitt
  • 56,863
  • 21
  • 114
  • 161
0

There are many ways to handle the returned data.

Set a variable with scope outside of that inline function and pass the value to it.

var result;

in callback result = arrayData;

You can also invoke a function to do other things with the result.

Chris Hasiński
  • 2,965
  • 2
  • 25
  • 34
  • I have tried what you suggested and was not able to make it work; I tried `result = arrayData;` and `callback(result = arrayData;)` – djq Jan 17 '11 at 00:36