2010-01-29 4 views
1

Il s'agit d'une question conceptuelle.Callbacks interdépendants dans la programmation webOS

La plupart des opérations effectuées dans webOS sont asynchrones. J'ai déjà fait de la programmation Ajax, mais j'ai l'impression que webOS l'amène à un nouveau niveau. Prenons l'exemple suivant d'une application qui extrait une liste des articles de presse du Web, et met également en cache des articles localement dans une base de données de stockage HTML5:

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 
}; 

Ainsi, parce que tout est asynchrone, nous essayons de créer la base de données et lire des articles mis en cache pendant que nous récupérons de nouveaux articles sur le Web. Parce que tout est fait par callbacks, je n'ai aucune confiance en ce qui va se passer en premier. La base de données sait quels articles ont été marqués comme "Favoris", mais en fonction de la vitesse d'exécution, this.model peut être vide (car le rappel db est en cours d'exécution) ou contenir des éléments (car l'AJAX est retourné en premier). Ainsi, chaque rappel doit être capable de remplir une liste ou d'itérer la liste et de faire des mises à jour.

Mon projet actuel ajoute une autre couche de complexité car j'utilise une liste de filtres, en ajoutant un autre rappel et un autre modèle au mélange.

Condenser cela en question:

  1. JavaScript est asynchrone, mais est-il un seul thread d'exécution? Dois-je m'inquiéter de deux fonctions modifiant this.model en même temps?
  2. Quels sont les moyens les plus courants de traiter des opérations asynchrones interdépendantes? (Par exemple. Éviter les doubles emplois dans this.model, où deux sources peuvent avoir des données qui se chevauchent pour le modèle)

Répondre

1

Sauf si vous utilisez explicitement worker threads, quelque chose a ajouté aux navigateurs récents et moteurs JS, callbacks Javascript ne seront pas exécutées à le même temps. Une technique courante consiste à utiliser un ensemble de drapeaux - si une opération dépend de cinq choses à faire, mettre un drapeau à 5, le décrémenter d'un avec chaque élément terminé, et faire vérifier chaque chose Si c'est zéro et si c'est le cas, exécutez une méthode de finalisation qui effectue l'action avec toutes les données collectées.

2

En réponse à ma question, je vois maintenant Mojo.Function.Synchronize:

Les instances de cette classe sont utilisés pour assurer un ensemble de fonctions de rappel sont tous appelés en même temps. Après la création, utilisez la méthode wrap() pour emballer les rappels que vous souhaitez synchroniser avant de les transmettre à un service asynchrone. L'objet synchronize différera l'appel de l'un d'entre eux jusqu'à ce que tous les wrappers renvoyés aient été appelés.