为什么我的异常没有被捕获?
Why isn't my exception being caught?
这是我得到的堆栈跟踪:
[Fault] exception, information=Error: Directory id 3 already in use
at cantrips.assets.index::AssetIndex/dirIdChanged()[/home/luismasuelli/Proyectos/flash-assets-index-ritual/assets-index-loader/src/cantrips/assets/index/AssetIndex.as:72]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at cantrips.assets.index::AssetDirectory/set id()[/home/luismasuelli/Proyectos/flash-assets-index-ritual/assets-index-loader/src/cantrips/assets/index/AssetDirectory.as:68]
at Main/updateSelectedDirectory()[/home/luismasuelli/Proyectos/flash-assets-index-ritual/assets-index-editor/src/Main.mxml:192]
at Main/__dirUpdateCurrent_click()[/home/luismasuelli/Proyectos/flash-assets-index-ritual/assets-index-editor/src/Main.mxml:401]
这是 Main/updateSelectedDirectory() 的实现:
private function updateSelectedDirectory():void {
try {
var newId:uint = uint(dirId.text);
var newName:String = StringUtil.trim(dirName.text);
var selectedDirectory:AssetDirectory = assetBrowserTree.selectedItem as AssetDirectory;
if (selectedDirectory) {
selectedDirectory.id = newId;
selectedDirectory.name = newName;
assetBrowserTree.expandItem(selectedDirectory.parent, false);
assetBrowserTree.expandItem(selectedDirectory.parent, true);
}
} catch (error:Error) {
Alert.show(error.message, "Cannot update");
}
}
为什么异常没有被try {} catch(error:Error) {}
捕捉到?
该异常是我创建的异常,具有一个很好理解的触发场景(我创建了异常并设计了这些场景,我正在测试它们;异常如我所料触发)。我还尝试在 catch 块中使用异常的确切名称 (AssetIndexError),并且不存在混淆或不明确的名称(这意味着:没有在其他地方声明的另一个 AssetIndexError class 我可以导入而不是这个)。
解释:
- cantrips.assets.index 是我可以控制的代码。
- 主要/*是主要的window。我也可以控制该代码。
截图:
如果您查看您的堆栈,您会发现错误并未在显示的代码(靠近堆栈底部)中抛出,而是在此处:
dirIdChanged
at AssetIndex.as:72
在堆栈的更下方,您将看到以下内容:
at flash.events::EventDispatcher/dispatchEvent()
这意味着堆栈在 AssetDirectory.set id()
和
AssetIndex.dirIdChanged()
添加事件处理程序时,当前块中的所有代码通常会 运行 在事件处理程序代码之前(因为它们不在同一线程中)。
所以在这种情况下,try/catch
中的所有代码都将在事件处理程序的代码之前有 运行 - 这就是错误未被捕获的原因。
任何时候处理一个事件,都需要另一个 try/catch,或者使用异步错误处理技术。
这是 OP 对已接受答案的补充。
这个麻烦的主要原因是我没看懂事件流是怎么做的
事件流是异步的,我以为是同步的。如果事件流是同步的,不难认为我的意图是正确的:异常可以在同一个执行堆栈中抛出,一切都会好起来的(即一个方法调用另一个方法,这样的方法调用第三个方法,等等等等异常和爆炸)。
当事件流像 ActionScript 流一样异步时,异常将在另一个执行堆栈中触发,但不知何故所提供的信息具有误导性,就像执行堆栈是相同的一样.
我实施的解决方案:一个愚蠢的对象(即一个愚蠢的新 class),它的行为类似于 EventDispatcher 但是同步的:.dispatch() 不会 post 对事件流的事件执行,而是自己执行已注册的事件处理程序,作为处理程序的循环,并手动调用每个处理程序,不可能在处理程序。
虽然从很多角度来看这个设计可能会被视为糟糕,但我同意,在这种情况下,它符合我对处理程序抛出异常和代码同步执行的需求。
这是我得到的堆栈跟踪:
[Fault] exception, information=Error: Directory id 3 already in use
at cantrips.assets.index::AssetIndex/dirIdChanged()[/home/luismasuelli/Proyectos/flash-assets-index-ritual/assets-index-loader/src/cantrips/assets/index/AssetIndex.as:72]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at cantrips.assets.index::AssetDirectory/set id()[/home/luismasuelli/Proyectos/flash-assets-index-ritual/assets-index-loader/src/cantrips/assets/index/AssetDirectory.as:68]
at Main/updateSelectedDirectory()[/home/luismasuelli/Proyectos/flash-assets-index-ritual/assets-index-editor/src/Main.mxml:192]
at Main/__dirUpdateCurrent_click()[/home/luismasuelli/Proyectos/flash-assets-index-ritual/assets-index-editor/src/Main.mxml:401]
这是 Main/updateSelectedDirectory() 的实现:
private function updateSelectedDirectory():void {
try {
var newId:uint = uint(dirId.text);
var newName:String = StringUtil.trim(dirName.text);
var selectedDirectory:AssetDirectory = assetBrowserTree.selectedItem as AssetDirectory;
if (selectedDirectory) {
selectedDirectory.id = newId;
selectedDirectory.name = newName;
assetBrowserTree.expandItem(selectedDirectory.parent, false);
assetBrowserTree.expandItem(selectedDirectory.parent, true);
}
} catch (error:Error) {
Alert.show(error.message, "Cannot update");
}
}
为什么异常没有被try {} catch(error:Error) {}
捕捉到?
该异常是我创建的异常,具有一个很好理解的触发场景(我创建了异常并设计了这些场景,我正在测试它们;异常如我所料触发)。我还尝试在 catch 块中使用异常的确切名称 (AssetIndexError),并且不存在混淆或不明确的名称(这意味着:没有在其他地方声明的另一个 AssetIndexError class 我可以导入而不是这个)。
解释:
- cantrips.assets.index 是我可以控制的代码。
- 主要/*是主要的window。我也可以控制该代码。
截图:
如果您查看您的堆栈,您会发现错误并未在显示的代码(靠近堆栈底部)中抛出,而是在此处:
dirIdChanged
at AssetIndex.as:72
在堆栈的更下方,您将看到以下内容:
at flash.events::EventDispatcher/dispatchEvent()
这意味着堆栈在 AssetDirectory.set id()
和
AssetIndex.dirIdChanged()
添加事件处理程序时,当前块中的所有代码通常会 运行 在事件处理程序代码之前(因为它们不在同一线程中)。
所以在这种情况下,try/catch
中的所有代码都将在事件处理程序的代码之前有 运行 - 这就是错误未被捕获的原因。
任何时候处理一个事件,都需要另一个 try/catch,或者使用异步错误处理技术。
这是 OP 对已接受答案的补充。
这个麻烦的主要原因是我没看懂事件流是怎么做的
事件流是异步的,我以为是同步的。如果事件流是同步的,不难认为我的意图是正确的:异常可以在同一个执行堆栈中抛出,一切都会好起来的(即一个方法调用另一个方法,这样的方法调用第三个方法,等等等等异常和爆炸)。
当事件流像 ActionScript 流一样异步时,异常将在另一个执行堆栈中触发,但不知何故所提供的信息具有误导性,就像执行堆栈是相同的一样.
我实施的解决方案:一个愚蠢的对象(即一个愚蠢的新 class),它的行为类似于 EventDispatcher 但是同步的:.dispatch() 不会 post 对事件流的事件执行,而是自己执行已注册的事件处理程序,作为处理程序的循环,并手动调用每个处理程序,不可能在处理程序。
虽然从很多角度来看这个设计可能会被视为糟糕,但我同意,在这种情况下,它符合我对处理程序抛出异常和代码同步执行的需求。