AIR SQLite – Utilisation de Responder en mode asynchrone
Jusque là, lorsque l'on exécutait des requêtes SQL en mode asynchrone, on ajouter des event listener pour récupérer le résutlat et l'erreur potentielle qui peut se produire lors du traitement. Vous pouvez voir un exemple dans le code présent dans cet article (partie mode asynchrone):
AIR SQLite – Création d'une base de données SQLite
Pour chaque SQLStatement, il faut ajouter 2 event listeners sans oublier de les retirer (removeEventListener) lorsque vous n'en avez plus besoin. Cette mécanique peut être un peu lourde et répétitive, c'est pourquoi il existe dans le framework Flex, un objet appelé Responder:
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/net/Responder.html
A ce Responder, vous allez passer en paramètre du constructeur, les références vers 2 méthodes: Une pour le RESULT et une pour ERROR.
Lorsque l'un de ces évènements se produit, la méthode correspondante sera appelée. Notez que vous n'avez plus besoin de manipuler les évènements, le Responder s'en occupe "under the hood".
Autre point important à noter, ce que vous récupérez est différent par rapport aux évènements que vous pouvez mettre en place. Lorsque vous utilisez un évènement, vous allez récupérer:
- un évènement de type SQLEvent ne contenant aucune information
- ou un évènement de type SQLErrorEvent contenant des informations sur l'erreur qui s'est produite
Avec un Responder, vous allez récupérer:
- un objet de type SQLResult contenant votre résultat
- un objet de type SQLError contenant des informations sur l'erreur qui s'est produite
Un Responder vous apporte donc plus de clarté dans votre code. Effet, pour récupérer le résultat d'une requête asynchrone en utilisant la mécanique évènementielle, vous devrez conserver (comme variable de votre classe par exemple) une référence vers le SQLStatement qui a fait la requête pour pouvoir en tirer le résultat.
Avec un Responder, vous récupérez directement l'objet qui vous intéresse, l'objet SQLResult. Votre classe sera donc plus propre car non pollué par des variables privées inutiles.
Pour utiliser un Responder, vous devrez indiquer à votre SQLStatement que vous voulez l'utiliser en le passant comme second paramètre de la méthode execute(). Si vous n'utilisez pas le premier paramètre (prefetch), passez la valeur "-1".
Exemple d'utilisation du Responder
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
horizontalAlign="left" viewSourceURL="srcview/index.html">
<mx:Script>
<![CDATA[
// -- IMPORTS ---------------------------------------------------------------- /
import vo.Contact;
// -- PROPERTIES ------------------------------------------------------------- /
private var conn:SQLConnection;
/**
* SQLStatement ré-utilisé lors de l'insertion
*/
private var q:SQLStatement = null;
private var _responder:Responder = null;
private var _contacts:Array = [new Contact(0, "A", "A", "A", "a@gmail.com", "M"), new Contact(1,
"B", "B", "B", "b@gmail.com", "M"), new Contact(2, "C", "C", "C", "c@gmail.com", "F"), new Contact(3,
"D", "D", "D", "d@gmail.com", "M"), new Contact(4, "E", "E", "E", "e@gmail.com", "F"), new Contact(5,
"F", "F", "F", "f@gmail.com", "M"), new Contact(6, "G", "G", "G", "g@gmail.com", "F")];
// -- AUTO INIT FUNCTIONS --------------------------------------------------- /
private function clickConnect():void {
conn = new SQLConnection();
var dbFile:File = File.applicationDirectory.resolvePath("employees.db");
// Event Listener that will tell us when the DB is opened
conn.addEventListener(SQLEvent.OPEN, openSuccess);
// Event Listener that will tell us if an error occurs
conn.addEventListener(SQLErrorEvent.ERROR, openFailure);
conn.openAsync(dbFile);
}
private function openSuccess(event:SQLEvent):void {
connLabel.text = "Database Status: Connected";
createTable();
}
private function openFailure(event:SQLEvent):void {
connLabel.text = "Database Status: Not Connected";
}
private function createTable():void {
var createStmt:SQLStatement = new SQLStatement();
createStmt.sqlConnection = conn;
var sql:String = "CREATE TABLE IF NOT EXISTS employees (id INTEGER PRIMARY KEY AUTOINCREMENT, " +
" firstName TEXT, lastName TEXT, middleInitial TEXT, email TEXT, gender TEXT)";
createStmt.text = sql;
createStmt.addEventListener(SQLEvent.RESULT, onCreateTableResult);
createStmt.addEventListener(SQLErrorEvent.ERROR, onCreateTableError);
createStmt.execute();
}
private function onCreateTableResult(event:SQLEvent):void {
connLabel.text = "Database Status: Connected and table created";
queryButton.enabled = true;
}
private function onCreateTableError(event:SQLErrorEvent):void {
connLabel.text = "Database Status: Can't create table";
queryButton.enabled = false;
}
private function callQuery():void {
if (_contacts.length == 0) {
// traitement terminé
// on valide la transaction
conn.addEventListener(SQLEvent.COMMIT, commitHandler);
conn.commit();
return;
}
if (!q) {
// on commence la transaction
conn.begin();
q = new SQLStatement();
_responder = new Responder(onQueryResult, onQueryError);
q.sqlConnection = conn;
var sql:String = "INSERT INTO employees (firstName, lastName, middleInitial, email, gender)" +
"VALUES (:firstName, :lastName, :middleInitial, :email, :gender)";
q.text = sql;
}
// on prend le premier élément de la queue que l'on supprime en même temps (shift)
var contact:Contact = _contacts.shift() as Contact;
q.clearParameters();
q.parameters[":firstName"] = contact.firstName;
q.parameters[":lastName"] = contact.lastName;
q.parameters[":middleInitial"] = contact.middleInitial;
q.parameters[":email"] = contact.email;
q.parameters[":gender"] = contact.gender;
q.execute(-1, _responder);
}
private function onQueryResult(sqlResult:SQLResult):void {
trace("onQueryResult");
callQuery();
// do something with the result if you wish
}
private function onQueryError(error:SQLError):void {
connLabel.text = "Database Status: Error in query: " + error.message;
// on annule la transaction entière
if (conn.inTransaction) {
conn.addEventListener(SQLEvent.ROLLBACK, rollbackHandler);
conn.rollback();
}
}
private function commitHandler(event:SQLEvent):void {
conn.removeEventListener(SQLEvent.COMMIT, commitHandler);
connLabel.text = "Transaction terminée.";
}
private function rollbackHandler(event:SQLEvent):void {
conn.removeEventListener(SQLEvent.ROLLBACK, rollbackHandler);
connLabel.text = "Rollback terminé";
}
]]>
</mx:Script>
<mx:Label text="SQLite Example" fontSize="18" fontWeight="bold" />
<mx:Label id="connLabel" text="Database Status: Not Connected" />
<mx:HBox>
<mx:Button id="connectButton" click="clickConnect()" label="Connect" enabled="true" />
<mx:Button id="queryButton" click="callQuery()" label="Insert" enabled="true" />
</mx:HBox>
</mx:WindowedApplication>
Articles similaires
- AIR SQLite – Utilisation des transactions (begin / commit / rollback) en asynchrone
- AIR SQLite – Utilisation des transactions (begin / commit / rollback) en synchrone
- AIR SQLite – Création de tables SQLite et types de données
- AIR SQLite – Typer les données renvoyées par un SELECT avec itemClass
- AIR SQLite – Création d'une base de données SQLite
Aucun trackbacks pour l'instant





