sql - AIR Sqlite: SQLEvent.RESULT not firing, but statement IS executing properly -
ok looks likes have stumbled upon strange timing issue... made quick sql wrapper class executing sql statements. after .execute() called, sqlevent.result event never fired, new entry in db created should be. really odd part if put settimeout() after calling execute() event fires expected.. hope i'm missing obvious here... here link example air app: http://www.massivepoint.com/airsqltest/airsql.zip
and here code wrapper class:
if down @ line 51 in sqlrequest class, see commented out settimeout() method. make work, uncomment line.. me doesn't make sense...
anyone have thoughts? i'm totally stumped here...
package com.jac.sqlite {//package import flash.data.sqlconnection; import flash.data.sqlstatement; import flash.events.eventdispatcher; import flash.events.sqlerrorevent; import flash.events.sqlevent; import flash.utils.settimeout; public class sqlrequest extends eventdispatcher {//sqlrequest class private var _callback:function; private var _dbconn:sqlconnection; private var _query:string; private var _params:object; private var _statement:sqlstatement; public function sqlrequest(callback:function, connection:sqlconnection, query:string, parameters:object=null):void {//sqlrequest trace("creating new sql request"); _callback = callback; _dbconn = connection; _query = query; _params = parameters; _statement = new sqlstatement(); _statement.sqlconnection = _dbconn; _statement.text = _query; if (_params != null) {//assign (var param:string in _params) {//params trace("setting param: " + param + " to: " + _params[param]); _statement.parameters[param] = _params[param]; }//params }//assign //setup events _statement.addeventlistener(sqlevent.result, handleresult, false, 0, true); _statement.addeventlistener(sqlerrorevent.error, handleerror, false, 0, true); }//sqlrequest public function startload():void {//execute _statement.execute(); //settimeout(handletimeout, 10000); }//execute //temp private function handletimeout():void {//handletimeout trace("executing: " + _statement.executing + " / " + executing); }//handletimeout private function handleresult(e:sqlevent):void {//handleresult trace("good sql request"); _callback(e); dispatchevent(e); }//handleresult private function handleerror(e:sqlerrorevent):void {//handleerror trace("sql error: " + e.errorid + ": " + e.error); //dispatchevent(e); }//handleerror public function executing():boolean {//get executing return _statement.executing; }//get executing public function query():string { return _query; } public function statement():sqlstatement { return _statement; } }//sqlrequest class }//package
i think you're missing here garbage collection.
haven't tested code, source of problem.
var sqlreq:sqlrequest = new sqlrequest(handleresult, _dbconn, sql); sqlreq.startload();
the reference sqlreq
local function , becomes unreacheable when function returns. makes collectable. guess there must code in air runtime collects garbage more agressively when there sql connections involved. because generally, you'll away not storing ref object (at least in web based environment, in experience; bug in such code, nevertheless; have in bad day experience it).
the settimeout
masks problem (or solves it, although in unintended way), because settimeout
function uses timer
internally. running timers not collected. so, timer alive , kicking , has reference sqlrequest
instance, makes reacheable, , so, not elligible collection. if db call takes longer timeout though, you're in same situation.
to solve this, store ref object , dispose when you're done.
edit
another option, if don't want change way calling code works, storing ref instance in class-scoped (i.e. static) dictionary duration of call (this dictionary shoul not use weak referenced keys obvious reasons).
you adding hidden side effect method, not sign of design in general, long remove when call db finished (whether succeded or not), you're safe, think problem more of style else.
what mean this:
private static var _dict:dictionary = new dictionary(); public function startload():void {//execute _statement.execute(); // add self reference dict instance won't collected // in last line, if have exception in execute, // code not run (or add try/catch if want, simpler // , cleaner, imo addtodict(); }//execute private function handleresult(e:sqlevent):void {//handleresult // remove self reference before running other code // (again, in case code follows throws) removefromdict(); trace("good sql request"); _callback(e); dispatchevent(e); }//handleresult private function handleerror(e:sqlerrorevent):void {//handleerror // same comment handleresult removefromdict(); trace("sql error: " + e.errorid + ": " + e.error); //dispatchevent(e); }//handleerror private function addtodict():void { _dict[this] = true; } private function removefromdict():void { if(_dict[this]) { delete _dict[this]; } }
Comments
Post a Comment