This documentation relates to previous versions of Titanium.

To see the latest documentation, visit docs.appcelerator.com.

Skip to end of metadata
Go to start of metadata

We all know from reading the Appcelerator wiki about Javascript best practices that global variables and polluting the global namespace are no-nos when writing good, maintainable code. However, we also know that old habits are hard to break - we are writing the code, we need "this" value set? Who cares?! Just create a global and be done with it!

The problem with this approach is that it will eventually come back to bite us; we will forget about the global variable, someone else won't be aware of it and, consequently, they will create some other way to get the same information. Worst of all - it won't always work.

Three notes we need to write on bright yellow stickies and attach to our monitor:

  1. We are going to write modular code (from now on, at least)
  2. Event-based programming is a good thing
  3. Global variables should be used only as a last resort

Get The Location

So, first, what is the problem? Getting the user's current location!

This will happen asynchronously, and the UI element we need to update is in another file. Of course, this is modular code!

We know that the API call Titanium.Geolocation.getCurrentPosition uses a callback to let us know when it has found a location.

Put it somewhere useful

Now we could create a global variable outside of the callback and use that to get the information.

but that only helps if the UI element we need to update is in the same JS file as the callback. That's not possible when writing modular code. Also, we definitely should not have UI code mixed in with the geolocation logic.

Put it somewhere better using an event listener

So what are we going to do? The first thing is to get rid of the global variable and fire an event to indicate that a location has been successfully received.

So now, anywhere in the application when we need to get the location information, we can create a listener to get the coordinates delivered in the event payload. This is nice; no globals necessary at all!

But there is another way; use a callback within the callback

Let's pass in a function to call when the device has finished getting the location. Along with firing the event, we will call the function passed in as a parameter with the coordinates we received from the device.

Somewhere else in our code we need to get the location and update the UI element with the information.

Modules are GOOD! That's what Kevin said!

Kevin Whinnery: Write Better JavaScript: video | slides

OK, now we have the GPS code in an include file, separated from the UI, and we can make calls from anywhere and get the location information from either an event or a callback. BUT we are not quite yet there - what about modules and CommonJS and all that "requires" stuff?

We want to be good Appcelerator citizens, producing code that is more code-strong than kitchen-sink! After all, the KitchenSink only exists to demonstrate API functionality, and not to act as a best-practice example.

Let's convert our location file into a module; just add "exports" before the function name to make it public.

In our ui.js file, where we created the window, we need to load the module containing the currentLocation function. In the complete example, we have named the file "maps.js", so we need to add the

statement.

Remember: don't include the ".js" extension when using require; it's not needed.

Then when you call the method it looks like this:

Here is the complete ui.js file

Summary

Using callbacks and events are good for your code; it encourages decoupling and better separation of business logic from the presentation layer. From now on, we will be strongly encouraging a more modular approach to application development, and this will be reflected in all the content we will be bringing you in the near future.

Keep coding strong!

The Code

CallbacksAreYourFriend on Github

Labels
  • None