Search code examples
javascriptasynchronousevent-handlingtitaniumpromise

asynchronous processing (callbacks in libraries + controllers)


My code is working fine, but I do not like at all.

I would like to split one file into two files, one containing webServices and another one with a controller.

My file do something like this:

File: Validacion.js (controller)

// Load next view
var MainView = Alloy.createController('index').getView('tabGroup');


// this a function call when I click a button "validar" on Validación View.
function btnClick(){

    var url = 'www.cocoloco.com/whatever';

    var webService = Ti.Network.createHTTPClient({
        onload: function(e){

            // open new view
            MainView.open();

            // close actual view
            $.tabValidacion.close();
            $.tabValidacion = null;

        },
        onerror: function(e){
            alert('onerror: ' + e.error);
        },
        timeout: 5000
    });

    webService.open('POST', url);
    webService.send();      

}

But I would like to do something like this below (divided in two files: webServices.js -library- and validation.js -controller-).

The problem is that I always have the message "error" because I pass throught "success = webServices.protocol();" but as far as it is "asynchronous" it doesn't stop and goes to following line of code without having server answer yet.

File: webServices.js (library)

exports.protocol = function(){

    var url = 'www.cocoloco.com/whatever';

    var webService = Ti.Network.createHTTPClient({
        onload: function(e){

            // on sucess exit with true
            return(true);

        },
        onerror: function(e){
            alert('onerror: ' + e.error);
            // on sucess exit with false
            return(false);
        },
        timeout: 5000
    });

    webService.open('POST', url);
    webService.send();      

}

File: Validacion.js (controller)

// Load next view
var MainView = Alloy.createController('index').getView('tabGroup');

function btnClick(){

    var webServices = require('webServices');

    var success = webServices.protocol();

    if(success){

        // open new view
        MainView.open();

    // close actual view
        $.tabValidacion.close();
        $.tabValidacion = null;

    }else{
        alert('error');
    }
}

I have thought about two possible options:

  • Using promises.

  • Fire a new event on "success" and use that event run another callback function (in this function I open the new view and close the previous one).

I do not know how difficult is this as far as the event is one file (library) and the callback function in another one (controller)

I have never used any of these solutions, so I do not know how "good" they are.

Any suggestion?


Solution

  • The callback approach works fine in most cases. Just pass the function as a parameter, you can return an object containing anything from a success message to responseText and status.

    webServices.js

    exports.protocol = function(callback) {
        var url = 'www.cocoloco.com/whatever';
    
        var webService = Ti.Network.createHTTPClient({
            onload: function(e){
                // on success call callback
                callback({ success: true });
            },
            onerror: function(e){
                // on error call callback
                callback({ success: false });
            },
            timeout: 5000
        });
    
        webService.open('POST', url);
        webService.send();      
    }
    

    Validacion.js

    function btnClick(){
        var webServices = require('webServices');
    
        webServices.protocol(function(e) {
            if(e.success){
                // open new view
                MainView.open();
    
                // close actual view
                $.tabValidacion.close();
                $.tabValidacion = null;
            } else {
                alert('error');
            }
        });
    }