views:

217

answers:

2

This is a conceptual question.

Many of the operations that happen in webOS are asynchronous. I have done Ajax programming before, but it feels like webOS takes it to a new level. Take the following example of an application that retrieves a list of news articles from the web, and also caches articles locally in an HTML5 storage database:

function FirstAssistant() {
}

FirstAssistant.prototype.setup = function() {
    this.controller.setupWidget('articleList',
        this.attributes = { itemTemplate: "article" },
        this.model = {}
    );

    this.db = openDatabase("FooArticles", "1.0");
};

FirstAssistant.prototype.activate = function() {
    this.db.transaction(function(transaction){
        transaction.executeSql(
            "CREATE TABLE IF NOT EXISTS 'articles' (name TEXT, favorite INTEGER DEFAULT 0)",
            [], this.successHandler.bind(this), this.errorHandler.bind(this)
        );
    });

   this.fetchArticles();
};

FirstAssistant.prototype.successHandler = function(transaction, results) {
    // SELECT from 'articles' to populate this.model
};

FirstAssistant.prototype.errorHandler = function(transaction, results) {
    // whatever
};

FirstAssistant.prototype.fetchArticles = function() {
    var request = new Ajax.Request(url, {
        method: 'get',
        onSuccess: this.fetchArticlesSuccess.bind(this),
        onError: this.fetchArticlesError.bind(this)
    });
};

FirstAssistant.prototype.fetchArticlesSuccess = function(request) {
    // populate this.model with new articles
};

FirstAssistant.prototype.fetchArticlesError = function(request) {
    // whatever
};

So, because everything is asynchronous, we are attempting to create the database and read cached articles while we fetch new articles from the web. Because everything is done via callbacks, I have no confidence in what will happen first. The database knows which articles have been marked as "Favorites," but depending on execution speed this.model may be empty (because the db callback is executing first) or it may have items in it (because the AJAX returned first). So, each callback needs to be able to populate a list or iterate the list and do updates.

My current project adds another layer of complexity because I am using a FilterList, adding another callback and model to the mix.

To condense this into questions:

  1. JavaScript is asynchronous, but is there only one thread of execution? Do I need to worry about two functions editing this.model at the same time?
  2. What are some common ways of dealing with interdependent asynchronous operations? (ie. preventing duplication in this.model, where two sources may have overlapping data for the model)
A: 

Unless you explicitly use worker threads, something added to recent browsers and JS engines, Javascript callbacks won't be executed at the same time.

One common technique is to use a set of flags -- if an operation depends on five things to be done, set a flag to 5, decrement it by one with each item that's completed, and have each thing check to see if it's zero and if so, run a finalization method that does the action with all the collected data.

Ben Combee
+1  A: 

As an answer to my own question, I now see Mojo.Function.Synchronize:

Instances of this class are used to ensure a set of callback functions are all called at the same time. After creating, use the wrap() method to wrap any callbacks you wish to synchronize before passing them to an asynchronous service. The synchronize object will defer calling any of them until all of the returned wrappers have been called.

Adam Backstrom