gpt4 book ai didi

sql - AIR Sqlite : SQLEvent. 结果未触发,但语句正在正确执行

转载 作者:行者123 更新时间:2023-12-03 16:27:02 25 4
gpt4 key购买 nike

好吧,看起来我偶然发现了一个奇怪的计时问题......我制作了一个快速的 SQL 包装类来执行 sql 语句。然而,在调用 .execute() 之后,SQLEvent.RESULT 事件永远不会被触发,但数据库中的新条目会按原样创建。真正非常奇怪的部分是,如果我在调用 execute() 之后放置一个 setTimeout() 事件会按预期触发..我希望我在这里遗漏了一些非常明显的东西......这是一个示例 air 应用程序的链接:
http://www.massivepoint.com/airsqltest/AIRSQL.zip

这是包装类的代码:

如果您向下看 SQLRequest 类中的第 51 行,您将看到注释掉的 setTimeout() 方法。为了使一切正常,只需取消注释该行..但对我来说这没有任何意义......

有人有什么想法吗?我完全被这里难住了......

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

最佳答案

我认为你在这里缺少的是垃圾收集。

尚未测试您的代码,但这肯定是问题的根源。

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

引用 sqlReq对函数来说是局部的,并且在函数返回时变得不可访问。这使它具有收藏值(value)。我想 AIR 运行时中一定有一些代码在涉及 sql 连接时更积极地收集垃圾。因为一般来说,您不会存储对您的对象的引用(至少在基于 Web 的环境中,根据我的经验;不过,这是此类代码中的一个错误;您只需要在糟糕的一天体验它)。
setTimeout掩盖了这个问题(或几乎解决了它,尽管是以一种意想不到的方式),因为 setTimeout函数使用 Timer内部。不收集正在运行的计时器。所以,计时器是活跃的,并且有一个对你的 SQLRequest 的引用。实例,这使得它可以到达,因此不适合收集。如果您的数据库调用时间比超时时间长,那么您又回到了同样的情况。

要解决此问题,请存储对对象的引用,并在完成后正确处理它。

编辑

另一种选择是,如果您不想改变调用代码的方式,则在调用期间将实例的引用存储在类范围(即静态)字典中(该字典不应使用弱引用键)出于显而易见的原因)。

您正在为您的方法添加隐藏的副作用,这通常不是良好设计的标志,但是只要您在对数据库的调用完成时将其删除(无论是否成功),您就安全了,所以我认为问题更多的是风格。

我的意思是这样的:
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];
}
}

关于sql - AIR Sqlite : SQLEvent. 结果未触发,但语句正在正确执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3330971/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com