异常的定义
异常用于处理用于指定的错误发生时改变脚本的正常流程。理解这句话需要知道两点:什么是程序指定的错误,什么是改变脚本的正常流程。指定的错误不同于语法错误,或者程序逻辑错误,它是一个特殊约束性事件。如在游戏中用户购买东西时如果金币不足,程序就会提示玩家金币不足,这就是异常,需要特殊处理。使用其他程序模块处理这个异常的动作就叫做 改变脚本的正常流程。
处理异常实现
异常处理的基本实现代码如下:
try {
$error = 'this is error';
throw new Exception($error); // 在try里面抛出一个异常对象,这个对象的构造函数参数是一个字符串
} catch (Exception $e) {
echo 'Caught exception' . $e->getMessage(); // 对异常处理
}
echo "process continue" // 异常处理后,程序不会中断,会继续执行
注意:抛出一个异常对象,对象的实例化参数是一个字符串
异常处理后,程序会继续执行
处理错误和异常的区别
在深入探讨异常处理之前,我们需要回答一个问题:为什么要使用异常呢,其实常用的错误处理方式也可以解决。例如购买东西时金块不足:
function buySomething()
{
if (checkMoney()) {
return "金币不足";
}
}
这个程序的问题是中断了程序的执行。因为我不仅要提示玩家金币不足,还可能需要引导用户充值,或者进行其他某些操作。还有一个更重要的问题是,函数嵌套调用的时候,如函数的调用关系:foo1()->foo2()->foo3()->fooN()。如果类似于fooN函数中每个都有错误返回值,这个可以看出错误处理的问题是:
1) 一级一级的返回错误消息.
2)每次都要判断一下是否错误.
3)还要处理不是自己的错误.
4) 每一级都要重复处理.
5) 还要知道被调用者将会调用什么, 会返回什么错误。
如果使用异常处理,就不会出现这样的问题,程序会捕捉这些异常,不需要每次都判断,而且还可以根据不同类型的异常使用不同的处理方式。
捕获多个异常
多个异常是指不同类型的异常。异常类可以被扩展。在我们游戏中,我们自己定义了几种异常类型:404异常,逻辑异常,SQL异常,框架类的核心异常。不同的异常类型有不同的处理方式。自定义异常类型代码如下:
class Core_Exception_Logic extends Core_Exception_Abstract
{
}
捕获多个异常
function dealException()
{
// 获取到异常对象
$e = $this->_request->getException();
if (! $e instanceof Exception) {
_exit('Access Denied');
}
try {
throw $e;
} catch (Core_Exception_403 $e) {
if (! isDebug()) {
header403();
}
} catch (Core_Exception_404 $e) {
header404();
} catch (Core_Exception_Logic $e) {
// 逻辑异常处理方式
}
return false;
}
异常处理方式
当我们获取到某个异常后,以什么样的形式反馈给玩家,在我们的项目中,如果是ajax请求则返回JSON数据,如果不是ajax请求,则直接输出到页面中。
catch (Core_Exception_Logic $e) {
if ($this->isAjax()) {
$this->jsonx($e->getMessage(), 'error');
} else {
_exit($e->getMessage());
}
}
知识点:
1)判断一个请求是否是ajax请求代码如下
public function isXmlHttpRequest()
{
return (strcasecmp(
$this->getServer('HTTP_X_REQUESTED_WITH'),
'XMLHttpRequest'
) ==0 ? true:false);
}
2)关于Json生成代码
public function json(array $output)
{
header('Content-type: text/json');
header('Content-type: application/json; charset=UTF-8');
exit(json_encode($output));
}
异常的集中捕获
如果使用异常,我们可能会有这样的一个疑惑:每次做一个动作的时候都要捕获抛出的异常,那么程序会不会出现很多 try {} catch(Exception $e) {} 这样的语句块,如果不小心忘了捕获某个异常,那后果就无法想象。是的,如果使用异常,的确会出现以上的问题,有一个方法可以解决这样的问题,那就是集中捕获异常。
集中捕获的意思是,使用一个方法捕获一些常见的异常。在很多框架中就实现了这样的功能,如zendframwork等,原理如下:
public function run($controllerPath = 'Controller')
{
try {
// 插件调用:路由解析前
Core_Plugin_Broker::invoke('routerStartup');
// 路由解析,设置当前分发信息
$this->setDispatchInfo(null);
if (!$this->_dispatchInfo) {
throw new Core_Exception_Fatal('No dispatchInfo found');
}
// 插件调用:路由解析后
Core_Plugin_Broker::invoke('routerShutdown');
// 插件调用:循环分发前
Core_Plugin_Broker::invoke('dispatchLoopStartup');
do {
$this->_dispatched = true;
// 插件调用:分发前
Core_Plugin_Broker::invoke('preDispatch');
// 执行分发
Core_Dispatcher::getInstance()->dispatch($this->_dispatchInfo, $controllerPath);
// 插件调用:分发后
Core_Plugin_Broker::invoke('postDispatch');
} while (!$this->_dispatched);
// 插件调用:循环分发后
Core_Plugin_Broker::invoke('dispatchLoopShutdown');
} catch (Exception $e) {
if ($this->_isCli) {
exit($e);
}
// 错误、异常处理控制器
$dispatchInfo = array(
'controller' => 'Error',
'action' => 'error',
'params' => array(
'exception' => $e,
),
);
Core_Dispatcher::getInstance()->dispatch($dispatchInfo, $controllerPath);
}
}
在程序执行入口处捕获,这样,就可以捕获到所有的异常,同时把捕获到的异常重新分发到一个集中的控制器里面处理(即采用捕获多个异常的方式)。这样既可以避免异常未捕获的问题,又可以减少许多代码,保证代码的整洁。
页面处理返回的异常信息
在我们游戏中,很多时候都是ajax请求,所以,异常信息常常是以json的形式返回给页面。在触发某个动作的时候,常常可能会抛一些逻辑异常,比如生命值不足,行动力不足,网络中断,或者金币不足等,那这里就有个困惑,如果每个ajax返回函数中都要处理这些异常,是不是显得特别复杂,如果有某些异常忘了处理,那错误信息就无法及时提示给用户。那我们能不能集中处理这些异常信息呢,答案是肯定的。主要原理就是在ajax返回函数内,写一个函数集中处理这些一次。核心代码如下:
$._get(href, function (resp) {
// 如果响应内容是JSON格式,说明在PHP抛了异常
if (typeof resp == 'object' && resp.status != undefined) {
// 优先处理一遍 _getJSON 的响应结果
if (! handlePriorAjaxResponse(resp)) {
return false;
}
}
});
异常处理的流程:
分享到:
相关推荐
c++异常处理实现标准c++异常处理实现标准
更好的异常处理实现JUnitAPIJava开发Java经验技巧共3页.pdf.zip
工作流技术通过信息技术的支持实现企业业务过程的自动化执行,是实现业务过程管理 与控制的一项关键性技术。目前,工作流技术已经...各种错误情况,采用人工与自动处理相结合的方式,实现异常处理与正常流程的分离。
关于VC++异常处理的详细中文文档,非常好的文档,对于GNU的异常处理有借鉴意义,而且原理很像
使用SpringBoot通过自定义注解+AOP+全局异常处理实现参数统一非空校验
课程作业,实现两数计算及其异常处理,异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰。 Java中的异常可以是函数...
主要介绍了Spring Cloud zuul自定义统一异常处理实现,需要的朋友可以参考下
这篇文章主要介绍了javascript异常处理实现原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一、什么是例外处理 当 JavaScript程序在运行中发生了诸如...
3.处理日志时,需要在每一个try-catch块包含一些处理代码,有时候异常处理的代码比正常执行代码还多,污染正常执行代码。 4.同样类型异常有不同的处理方式,使最终的处理变得复杂。 5.接口抛出异常,破坏封装,打破...
(1)必须是6位的数字符号的字符串,如“123456”。 ... ... (4)用户的输入动作是随意的,可以输入任意符号。...符组成的字符串,就必须进行异常处理,请自定义异常来处理各种可能出现的异常,并能给出每种异常的原因
Spring Cloud Gateway的全局异常处理 Spring Cloud Gateway中的全局异常处理不能直接用@ControllerAdvice来处理,通过跟踪异常信息的抛出,找到对应的源码,自定义一些处理逻辑来符合业务的需求。 网关都是给接口做...
主要为大家详细介绍了MySQL定义异常和异常处理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
用C语言实现的异常处理库,使用的方法与C++、Java的异常处理类似。
将所有类型的异常处理从各处理过程解耦出来,这样既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护。使用统一异常处理的好处是能够将异常信息统一捕捉并组装成固定格式的数据返回。
在开始进行自定义的异常处理逻辑之前,我们有必要看一下异常处理的默认实现。也就是:为什么会产生上面小节提到的现象? ResponseErrorHandler是RestTemplate请求结果的异常处理器接口 o接口的第一个方法hasError...
使用C语言实现的异常处理,上次上传的文件里有东西编译不过,是因为那些是项目中使用的一些封装,在此致歉。这次上传的是我新修改的,代码里有一个简单的例子。使用时候需要将main函数去掉
本文讨论编译器怎么实现异常处理。假设读者熟悉异常处理的语法。本文包含一个异常处理的VC++的库来替代VC++的异常处理,使用这个函数: install_my_handler(); 在这以后,程序中发生的任何异常(包含抛出...
6. Microsoft 对于的实现版本中的异常处理 7. 部分构造及 placement delete 8. 自动删除,类属 new 和 delete、placement new 和 placement delete 9. placement new 和 placement delete,及处理构造函数抛出的异常...
该代码给出了基本的异常处理操作(throw catch等),用C++实现