Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Managing Synchronous and Asynchronous JavaScript Functions with jQuery's Deferred

I need to run a series of calls over websockets via Socket.IO (client-side). Since I'm not using $.ajax, jQuery's deferred functions won't integrate as well and I'll have to manually handle promises. With every websocket call, I pass a callback and I'm quickly seeing how this project could spiral out of control. Here's a simplified example of how my websocket calls work (excluding all connection handling code):

function js2node(nodeFunction, data, callback){
    socket.emit('incoming', nodeFunction, data, callback);
}

function sampleServerCall(){
    js2node('sampleCall', 'something', 'sampleCallback');
}

function sampleCallback(json){
    // Handle data
}

sampleServerCall();

I will be talking to the server quite a bit, all calls will be asynchronous, but some will need to come back in a specific order. Enter jQuery deferred. Here is some working code:

var deferredArray = [];

$(function(){
    $.when(  // Any order
        getData1(),
        getData2()
    ).then(function(){  // Must have responses from dataCallback1 and dataCallback2 before doing this...
        $.when(  // Any order
            getData3(),
            getData4()
        ).then(function(){  // Must have responses from dataCallback3 and dataCallback4 before doing this...
            getData5();
        });
    });
});

function getData1(){
    js2node('data1', 'something', 'dataCallback1');
    deferredArray[0] = new $.Deferred();
    return deferredArray[0].promise();
}

function getData2(){
    js2node('data2', 'something', 'dataCallback2');
    deferredArray[1] = new $.Deferred();
    return deferredArray[1].promise();
}

function getData3(){
    js2node('data3', 'something', 'dataCallback3');
    deferredArray[2] = new $.Deferred();
    return deferredArray[2].promise();
}

function getData4(){
    js2node('data4', 'something', 'dataCallback4');
    deferredArray[3] = new $.Deferred();
    return deferredArray[3].promise();
}

function getData5(){
    js2node('data5', 'something', 'dataCallback5');
    deferredArray[4] = new $.Deferred();
    return deferredArray[4].promise();
}

function dataCallback1(json){
    // Handle data
    deferredArray[0].resolve();
}

function dataCallback2(json){
    // Handle data
    deferredArray[1].resolve();
}

function dataCallback3(json){
    // Handle data
    deferredArray[2].resolve();
}

function dataCallback4(json){
    // Handle data
    deferredArray[3].resolve();
}

function dataCallback5(json){
    // Handle data
    deferredArray[4].resolve();
}

As you can see, I'm still stuck with nested callbacks from the way I'm using when/then and nesting could potentially go deeper as I add functionality. Deferred is a new concept to me but I've read it's supposed to help in situations such as this. I feel like there has to be a better way than what I'm currently doing. Can anyone help me set this up more efficiently?

like image 854
CauselessEffect Avatar asked Apr 30 '26 11:04

CauselessEffect


1 Answers

You can do more with .then:

$(function(){
    $.when(
        doSock('data1', 'something'),
        doSock('data2', 'something')
    ).then(function(data1, data2){
        return $.when(
            doSock('data3', 'something'),
            doSock('data4', 'something')
        );
    }).then(function(data3, data4){
        return doSock('data5', 'something');
    });
});

That way your nesting never goes deeper than that.

(i used adeneo's helper method)

like image 103
Kevin B Avatar answered May 03 '26 01:05

Kevin B



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!