Matt
Matt

Reputation: 549

Execute multiple functions with parameters to be fired in order on ajax sucess

I'm attempting to write a couple of functions using jQuery to help me test some api endpoints that I'm writing in php. I'm a novice when it comes to Javascript and jQuery and I'm having difficulty working out what I need to read up on in order to get things working that way I need it.

Here are the requirements I'm attempting to meet:

I've read the jQuery docs and believe that deferred and promises are possibly the avenue I should be pursuing but I am not able to get an example working.

Simplified versions of my two functions:

(For clarity)

// Returns data from an api request providing something hasn't gone horribly wrong
function api( api, method, endpoint, query ) {
    $.ajax({
        type: method,
        url: '/api/' + api + '/' + endpoint,
        data: query,
        dataType: 'json',
        success: function(data) {

            // I currently have a single hardcoded function
            populate( data.result, '#resource', null );

        },
        error: function( data ) {
            // Debug
            dump(data.result);
        }
    });

    // Do some other stuff here
}

// Example call
$('body').on('click', '#bigFatButton', function() {

    // I would like to specify a function (or chain of functions)
    // to be fired on success along with the api() function

    api('resources', 'get', 'document', {
        debug: '1',
        id: '7'
    })

});

This is what I'd like to achieve (something nice, short and reusable):

fn1() and fn2() are fired in order and can both access the data returned by api()

api('resources', 'get', 'document', {
    debug: '1',
    id: '7'
}).fn1(data, 'custom', 'params').fn2(data, {other: 'params'}).alert('wooty!');

What would be the best way of achieving something similar to this? A nudge in the right direction would be very much appreciated!

Thank you.

Upvotes: 0

Views: 122

Answers (3)

Alex Pereira
Alex Pereira

Reputation: 966

1 - I would use the methods as arguments in an anonymous function

api('resources', 'get', 'document', {
    debug : true, // better to say true or false :)
    id : 7, // if your id is a number use number
    callback : function(data){
        fn1(data);
        fn2(data);
    }
});

2 - Using an array, could be cool if you have a lot to run.

// in api method..
for(var i; i < cbks.lengths; i++){
    cbks[i](); // execute one by one the callbacks declared.
}

api('resources', 'get', 'document', {
    debug : true, // better to say true or false :)
    id : 7, // if your id is a number use number
    [fn1, fn2, fn3] // here are the callbacks
});

Upvotes: 0

guest271314
guest271314

Reputation: 1

Try adding return statement before $.ajax() , returning data from api , utilizing .then()

function api( api, method, endpoint, query ) {
    // return `$.ajax()` jQuery promise to `.then()`
    return $.ajax({
        type: method,
        url: '/api/' + api + '/' + endpoint,
        data: query,
        dataType: 'json',
        success: function(data) {

            // I currently have a single hardcoded function
            populate( data.result, '#resource', null );
            // return `data`
            return data

        },
        error: function( data ) {
            // Debug
            dump(data.result);
        }
    });

    // Do some other stuff here
}

// Example call
$('body').on('click', '#bigFatButton', function() {

    // I would like to specify a function (or chain of functions)
    // to be fired on success along with the api() function

    api('resources', 'get', 'document', {
        debug: '1',
        id: '7'
    }).then(function(data) {
         $.when(fn1(data, 'custom', 'params')
               , fn2(data, {other: 'params'})
         .then(function() {alert('wooty!')})
    })

});

Upvotes: 2

Mouser
Mouser

Reputation: 13304

Due to the asynchronous nature of AJAX you can't chain functions directly from the API function. The data would simply not be available when the chained functions are ran. However you can do it inside the success function. You will need to construct a wrapper function.

function wrapper()
{
    return {
       fn1 : function(data){
           //execute code for fn1 here
           return wrapper();
       },
       fn2 : function(data){
           //execute code for fn2 here
           return wrapper();
       },
       alert : window.alert.bind(window);
       }
    }
}

By running wrapper.fn1(data, arguments).fn2(data, arguments).alert("whoot!") inside the success function it will work the way you intended.

Everytime you call upon the wrapper function, or a function inside it it will return the full object allowing for function chaining.

A more efficient design would be to construct the functions outside the wrapper object and only reference them inside the wrapper function.

Upvotes: 0

Related Questions