Search code examples
javascripthttpclienttitaniumreturnappcelerator

Titanium HTTPClient returns too 'fast'


I have the following function:

  getTasks: function()
    {
        var taskRequest = Titanium.Network.createHTTPClient();
        var api_url = 'http://myawesomeapi.heroku.com/users/' + Ti.App.Properties.getString("userID") + '/tasks';

        var tasks = [];
        taskRequest.onload = function() {
            var response = JSON.parse(this.responseText), 
            len = response.length,
            i = 0,
            t;

            for(; i < len; i++)
            {
                task = response[i];
                var newTask = {};
                newTask.rowID = i;
                newTask.title = task.title;
                newTask.description = task.description;
                newTask.id = task.id;
                newTask.hasChild = true;

                tasks.push(newTask);
            }

            alert(tasks);
        }

        taskRequest.open('GET', api_url, false);
        taskRequest.setRequestHeader('Content-Type', 'application/json');
        taskRequest.send();

        alert(tasks);
            // return tasks;
    }

This function is in my controller; I call it in my view when I need to load the data in. However, I wish to return this data so I can assign it to a variable in the view.

Now what happens is that it returns emptiness. The last alert (bottom one) seems to be running too fast and it returns an empty array, while the one that only gets alerted after the onload function is done, contains what I need.

Now my obvious question, how can I get my function to return the array with the data, instead of without?

Putting a timer on it seems hardly the right decision.. Thanks!


Solution

  • "However, I wish to return this data so I can assign it to a variable in the view."

    Aside from making the AJAX request synchronous (which you probably don't want), there isn't any way to return the data.

    Whatever code relies on the response needs to be called from within the response handler.

    Since functions can be passed around, you could have your getTasks method receive a callback function that is invoked and will receive the tasks Array.

      getTasks: function( callback ) // receive a callback function
        {
            var taskRequest = Titanium.Network.createHTTPClient();
            var api_url = 'http://myawesomeapi.heroku.com/users/' + Ti.App.Properties.getString("userID") + '/tasks';
    
            taskRequest.onload = function() {
    
                var tasks = [];
    
                // code populating the tasks array
    
                alert(tasks);
    
                callback( tasks ); // invoke the callback
            }
    
            taskRequest.open('GET', api_url, false);
            taskRequest.setRequestHeader('Content-Type', 'application/json');
            taskRequest.send();
        }
    

    So you'd use it like this...

    myObj.getTasks(function(tasks) {
        alert('in the callback');
        alert(tasks);
          // Any and all code that relies on the response must be
          //   placed (or invoked from) inside here
        some_other_function();
    });
    
    function some_other_function() {
    
        // Some more logic that can't run until the tasks have been received.
        // You could pass the tasks to this function if needed.
    
    }