in Appcelerator Titanium, Mobile

Creating an Alloy Library for Appcelerator Titanium: xhr.js

Background

Part of my consulting work entails helping customers with their existing Titanium projects, which means I spend a lot of time working with other people’s code. When working with companies that are newer to Titanium development, I have noticed that many projects may have code being repeated across controllers, or that they have spent a lot of time trying to expose function in a controller for re-use in other controllers, or that they are putting a lot of logic inside of model files.

We can avoid many of these issues, as well as make our code easier to re-use and just keep things DRY with the use of alloy libraries.

Using Alloy Libraries

Alloy Library code is a great tool inside of Alloy. One reason new Titanium developers may not use alloy libs at the beginning of their project is that their existence isn’t immediately apparent inside new Alloy projects. More on this below.

Building Our first Alloy Lib – xhr.js

For our code example, we’re going to create a simple library for doing Ti.Network.HTTPClient requests in our app.

In Titanium, we use HTTPClient for connecting our apps to remote servers and APIs. For those coming from a web background, you’re probably familiar with XMLHttpRequest, and HTTPClient operates in a similar fashion. For more info, check out the docs for HTTPClient and the Request Lifecycle.

I have chosen to base our example on HTTPClient for two reasons:

  1. Pretty much all apps have to do network requests to an API of some sort, and depending on how things are structured, these requests may take place in different parts of your code. A perfect opportunity for enabling re-use!

  2. The HTTPClient is often the first introduction to asynchronous code for developers new to Titanium and programming in general (this was the case for me!), and can be confusing at first. We’re going to get exposure to it right away, and be good to go!

Step 1. Create the Library

First, create a new Titanium Alloy project, or open an existing one.

In Alloy, library files live under app/lib directory. By default, new Alloy projects don’t have a lib folder, so if you don’t see it in your project, go head and create the lib file (this goes back to what I mentioned earlier about library files not being immediately apparent in Alloy projects).

Ok, let’s create a new file called xhr.js and place it under lib.

app/
├──lib
   └── xhr.js

We’re done! Our first Alloy library is official! 🙂 Well, let’s add some more stuff.

As with Alloy Controllers, libraries are CommonJS files. CommonJS is a big topic, so the streamlined explantation is that it helps us keep our code reusable and helps in not accidentally overwriting other variables or parts of our code by what’s commonly referred to as scope or namespace pollution. For more info, check out this great explanation.

For now, the main thing we need to know about CommonJS is that any function we want to be called from outside of our library needs to be added to the exports property.

Step 2. Our First Function

Ok, let’s create a test function. This won’t be part of our real xhr.js library, but will serve as an introduction. We will create a simple function called logDate, then enable the function be accessible via the CommonJS exports property. Think of the exports property as how we define the API for our library. We can create as many different functions via exports as we need.

In our file, do this:

//xhr.js

function logDate(name){
  console.log('Hi ' + name + ', it is currently ' + new Date());
};

//export or expose our logDate function 
exports.logDate = logDate;

Let’s now use our lib in Alloy’s index.js controller by requiring the xhr lib, then calling the logDate function. Note that when we require the lib, we just reference the file name, and not reference the path to lib. Alloy already knows to look there.

//index.js

//this is how we load our module.
//Note we don't have to add a 'lib' to the path, just the file name
var xhr = require('xhr');

//execute our logDate function and pass a string
xhr.logDate('Adam');
//Hi Adam, it is currently Tue Apr 18 2017 08:35:21 GMT-0400 (EDT)

Hey, that was easy!

Ok, that’s all beginner stuff, right? Let’s recap:

  1. In our xhr.js lib, we created a function called logDate that accepts a name and prints it to the console.
  2. In order to call the function for use in our index.js controller, we expose it via the exports CommonJS property.
  3. In index.js, we require our xhr lib and
  4. When we are ready to log the date and time, we run xhr.logDate('Adam') passing it a string.

Step 3. Building out xhr.js

With the intro out of the way, let’s get into building a library we can use in pretty much any Alloy project we have.

I use some variant of this library all the time. On top of that, I can never remember how to set up HTTPClient!

I mentioned previously the reasons for doing an example with HTTPClient. Another reason for making this is that I use some variant of this library all the time. On top of that, I can NEVER REMEMBER how to set up HTTPClient! It is easier for me to load my lib and pass it a couple of relevant properties and leave it at that!

Three New Things
  1. More parameters In our logDate example, we passed a single name string to our library. In our full-blown version, we have a lot more options to send, and therefore more parameters are needed. Rather than sending a bunch of individual parameters, we will just pass as single Object and make our parameters into properties of that object. This way, we don’t have to keep track of the order of parameters, and when we inevitably add a new one, we don’t have to do additional work in the function call.

  2. Hello Asynchronous Callbacks Two of our new parameters are success and error. These are actually going to reference functions which will be run as our callbacks. More info on this later!

  3. Requiring underscore.js Notice we are requiring the Alloy built-in underscore.js library. Wait, we can require a library from within a library? Yes! Underscore.js is an excellent utility library, and since it comes built in to

Our library will have one public method, called send, which lets us pass properties to it to then make the http request.

Parameters
  • method – such as GET, POST, etc
  • url – our api endpoint that we need to reach
  • success – a success callback
  • error – an error callback, for when the request fails
Our new xhr.js

Back in our xhr.js lib, you can remove our previous example code. We’re going to implement a function simply called send, that will allow us to connect to our API endpoint specified in the url property, then either return the data via success callback, or handle the request error in the error callback.

//xhr.js

//alloy built-in libs like underscore and moment.js are prefaced with 'alloy/' in the path
var _ = require('alloy/underscore');

function send(args) {
    var request = Titanium.Network.createHTTPClient();

    request.onload = function() {
        //Use an underscore helper function to check that we
        //have a function in args.success before calling it
        if(_.isFunction(args.success)){
            //Here we call the callback
            args.success(this.responseText);
        }
    };

    request.onerror = function(e) {
        if(_.isFunction(args.error)){
            args.error(e);
        }
    };

    request.open(args.method, args.url);
    request.send();
};

exports.send = send;

When we use the xhr lib now, the main differences to note is now we are passing our parameters in a single object. We are also defining onSuccess() and onError functions that get passed to xhr and later used as callbacks. Read more about asynchronous callbacks.

//index.js

//require the library
var xhr = require('xhr');

function onSuccess(res){
    //do something with our fetched data
}

function onError(e){
    //handle our request error
}

//here is where we make the request
xhr.send({
    url: 'http://example.com/api/ourendpoint',
    method: 'GET',
    success: onSuccess,
    error: onError
});

Recap

Woo hoo! We have built our own xhr library. Of course, this is a fairly simple implementation and doesn’t cover stuff like how to add headers, post data, etc. For a full implementation of an xhr.js library, check out my example at: https://github.com/adampax/TiJazzCon.

Further Customization and Code Re-use

The main thing I want you to take away from this tutorial other than how to create and use Alloy libraries, is that with libraries, we can simplify our controller code by moving stuff like the XHR requests into into reusable libraries. We can then customize our libraries any way we need them.

For example, let’s say don’t want to always send an error callback, optionally passing to a default error handler. In our library, we can do:

request.onerror = function(e) {
    if(_.isFunction(args.error)){
        args.error(e);
    } else {
        //our default error handler
        console.error('xhr error', e);
    }
};

This makes it even easier to send a request using our library.

Next Steps

Next up, we will be adding JavasScript Promises to an Appcelerator Alloy library to help us work with the asynchronous nature of HTTPClient.

That’s it for now, be sure to check out the finished xhr.js and let me know what cool Alloy libraries you are creating!