2010-07-25 3 views
4

좋아요. 이상한 타이밍 문제를 발견 한 것 같습니다. SQL 문을 실행하기위한 빠른 SQL 래퍼 클래스를 만들었습니다. 그러나 .execute()가 호출 된 후 SQLEvent.RESULT 이벤트는 실행되지 않지만 DB의 새 항목은 있어야하므로 작성됩니다. 실제로 정말 이상한 부분은 execute()를 호출 한 직후에 setTimeout()을 놓으면 예상되는 이벤트가 발생하는 것입니다. 여기에 정말 분명한 뭔가가 빠졌 으면 좋겠습니다. 여기에 예제 air app : 에 대한 링크가 있습니다. 당신이로 SQLRequest 클래스에서 라인 (51)을 내려다 보면AIR Sqlite : SQLEvent.RESULT가 실행되지 않지만 문이 올바르게 실행 중입니다.

, 당신은 주석에서는 setTimeout() 메소드가 표시됩니다 여기

그리고 http://www.massivepoint.com/airsqltest/AIRSQL.zip는 래퍼 클래스에 대한 코드입니다. 모든 것이 작동하도록하려면 그 줄을 주석 처리하십시오. 그러나 나에게 이것은 어떤 의미가 없습니다 ...

누구든지 어떤 생각을 가지고 있습니까? 나는 완전히 여기에서 곤란하다. ...

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 
    for (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 get executing():Boolean 
    {//get executing 
    return _statement.executing; 
    }//get executing 

    public function get query():String { return _query; } 
    public function get statement():SQLStatement { return _statement; } 

}//SQLRequest Class 

}//Package 

답변

1

나는 당신이 여기에서 쓰레기를 모으고 있다고 생각한다.

코드를 테스트하지 않았지만 이것이 분명히 문제의 원인 일 수 있습니다.

var sqlReq:SQLRequest = new SQLRequest(handleResult, _dbConn, sql); 
sqlReq.startLoad(); 

참조 번호 sqlReq은 함수에 지역적이며 함수가 반환 할 때 연결할 수 없게됩니다. 그것은 그것을 수집 할 수 있습니다. 거기에 SQL 연결이 관련된 때 더 적극적으로 가비지 수집하는 AIR 런타임에서 일부 코드가 있어야합니다 같아요. 왜냐하면 일반적으로 객체에 대한 참조를 저장하지 않기 때문에 (적어도 웹 기반 환경에서는 내 경험에 따라 이러한 코드에서 버그가 발생하지만 경험이 부족한 날이기도합니다. 그것).

setTimeout 함수는 내부적으로 Timer을 사용하기 때문에 setTimeout은이 문제를 숨기거나 의도하지 않은 방식으로 거의 해결합니다. 실행중인 타이머는 수집되지 않습니다. 따라서 타이머가 살아 있고 발로 움직이며 SQLRequest 인스턴스에 대한 참조가 있습니다.이 인스턴스는 재사용이 가능하므로 수집에 적합하지 않습니다. DB 호출이 시간 초과보다 오래 걸리면 같은 상황으로 돌아온 것입니다.

문제를 해결하려면 객체에 대한 참조를 저장하고 완료되면 올바르게 처리하십시오.

편집

또 다른 옵션은, 당신이 기간 동안 클래스 범위의 (즉, 정적) 사전에있는 인스턴스에 대한 심판을 저장하고, 당신이 작동하는 코드를 호출하는 방법을 변경하지 않으려면 전화 (이 사전은 이 아니며 명백한 이유 때문에 약한 참조 키를 사용합니다.).

일반적으로 좋은 디자인의 징후는 아니지만 DB에 대한 호출이 완료되면 (성공 여부와 상관없이) 제거한 한 숨겨진 부작용을 메서드에 추가합니다. 안전하다. 그래서 문제는 다른 어떤 것보다 스타일이 더 중요하다고 생각한다. 그 ... 그 지적 주셔서 너무 감사했다

private static var _dict:Dictionary = new Dictionary(); 

public function startLoad():void 
{//execute 
    _statement.execute(); 
    // add a self reference to dict so the instance won't be collected 
    // do this in the last line, so if we have an exception in execute, this 
    // code will not run (or add a try/catch if you want, but this is simpler 
    // and cleaner, IMO 
    addToDict(); 
}//execute 

private function handleResult(e:SQLEvent):void 
{//handleResult 
    // remove the self reference before running any other code 
    // (again, this is in case the code that follows throws) 
    removeFromDict(); 
    trace("Good SQL Request"); 
    _callback(e); 
    dispatchEvent(e); 
}//handleResult 

private function handleError(e:SQLErrorEvent):void 
{//handleError 
    // same comment as 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]; 
    } 
} 
+0

aahh 쓰레기 :

내 말은이 같은 것입니다! – Jake

관련 문제