5

I'm fairly new with jQuery, and I'm trying to call two functions on successful ajax (since the documentation says as of 1.5 success callback can take an array of functions).

If I do this, everything works fine:

$.ajax({
    url : sJSONFilePath,
    dataType : 'json',
    success : foo(data)
});

What do I need to do to pass in an array of functions? If I try the following, I get a "Uncaught TypeError: Cannot read property 'length' of undefined" error in the console:

$.ajax({
    url : sJSONFilePath,
    dataType : 'json',
    success : [foo(data), bar(data)]
});

I was unable to find any examples of this feature being used. Thanks in advance, and sorry if this is dumb.

1
  • 2
    Unless foo returns a function, then this success : foo(data) doesn't work as well as you may think. You're invoking foo immediately instead of passing it as a callback. Commented Feb 2, 2012 at 22:38

4 Answers 4

13

There's no need for an array, you can use the deferred syntax that was also introduced in jQuery 1.5:

$.ajax(...).done(foo).done(bar);

This is generally cleaner and much more extensible than passing callback functions as parameters to $.ajax and relatives.

From the $.ajax() documentation:

The jqXHR objects returned by $.ajax() as of jQuery 1.5 implement the Promise interface, giving them all the properties, methods, and behavior of a Promise (see Deferred object for more information). For convenience and consistency with the callback names used by $.ajax(), jqXHR also provides .error(), .success(), and .complete() methods. These methods take a function argument that is called when the $.ajax() request terminates, and the function receives the same arguments as the correspondingly-named $.ajax() callback. This allows you to assign multiple callbacks on a single request, and even to assign callbacks after the request may have completed. (If the request is already complete, the callback is fired immediately.)

[but see the paragraph after, where it explains how .success, .error and .complete are now deprecated and replaced with .done, .fail and .always]

Sign up to request clarification or add additional context in comments.

5 Comments

This works. Does $.done pass (data, textStatus, jqXHR) to foo and bar just like success does? I don't know much about Deferred
@MJS yes, it does - I'll add some text.
Just a note for anyone happening upon this: The documentation appears to suggest that the callbacks are executed in serial.
@KevinDice of course - they can't possibly be executed in parallel
I mean synchronously rather than async.
5

What you do is this:

$.ajax({
    url : sJSONFilePath,
    dataType : 'json',
    success : function(data) {
        foo(data);
        bar(data);
    }
});

or this:

$.ajax({
    url : sJSONFilePath,
    dataType : 'json',
    success : [foo, bar]
});

Note that in the second one, I'm not calling foo and bar, I'm listing the function references in an array (since as you say, as of 1.5 jQuery's ajax callback options allow that).


You've said that this works fine:

$.ajax({
    url : sJSONFilePath,
    dataType : 'json',
    success : foo(data)
});

but it doesn't. What that does is immediately call the foo function, and then assign the return value of that function to the success property of the options you're passing to ajax. Unless you're using foo to build and return a function to use as the callback, that's not what you want to do.

It's important to understand the difference between calling a function and using a reference to it. If you have parens after the function name (with or without arguments in them), you're calling it. If you just have the name, you're referring to it. E.g.:

var f = foo(); // CALLs `foo` and assigns return value to `f`
var f = foo;   // Assigns a reference to `foo` to `f`

6 Comments

This is perfect. I think my JS was cached, and that's why it worked with my borked code. I'll mark this as answer after 15 mins. Thanks for the thorough reply!
@amnotiam except for completely missing out usage of deferred object syntax, which is now the preferred way to do AJAX callbacks...
@Alnitak: Fair point, though I'd consider deferreds to be alternate instead of preferred
@amnotiam well, I prefer it - I've used both and I'd never to back to the old way now ;-)
While this post was very informative and answered my question exactly (much, much appreciation), I ended up using the .done() solution above. Thank you very much for your time and help.
|
1

when writing

success : [foo(data), bar(data)]

you are in fact evaluating the foo and bar functions (probably with a null argument)

you need to write

success : [foo, bar]

Comments

0

Why don't you call one function that calls the other two:

$.ajax({
    url : sJSONFilePath,
    dataType : 'json',
    success : foo_bar(data)
});

function foo_bar(data)
{
   foo(data);
   bar(data);
{

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.