在 try-catch 块中继续当前迭代 | PHP

Posted

技术标签:

【中文标题】在 try-catch 块中继续当前迭代 | PHP【英文标题】:Continue with current iteration in a try-catch block | PHP 【发布时间】:2020-02-28 23:22:23 【问题描述】:

在我的脚本中有时会出现服务器、连接、配置或 API 问题,因此我实现了一个 try-catch 块来正确捕获异常并跳过它们。

...但是我的问题并没有用这个解决方案解决,因为元素(引发问题)不是问题本身。 所以基本上我的问题是是否有任何方法可以捕获错误并从您离开的地方继续:不跳过错误并转到下一个元素,而是在 foreach 循环中重复当前迭代。

显然,continuebreak 不起作用!

foreach($xx as $x) 
    try 
        //main code
     catch (Exception $e) 
        echo 'Caught exception: ', $e->getMessage(), "\n";
        sleep(10);
    

... 当 catch 部分捕获错误时,代码应该使用当前的 $x 重复 try 循环(它最初在其上捕获错误/抛出错误),然后继续处理元素列表。

【问题讨论】:

将 try 块放入自己的while (true) 循环中,成功后您可以break 您能进一步解释一下吗?您的解决方案应该是:while (true) try //main code 并在 catch 中休息一下? @deceze 如果您使用代码语法提交答案可能会更好? :) 【参考方案1】:

您可以运行 for 循环而不是 foreach 循环,并且可以通过递减它来管理 catch 块内的增量计数器以获取当前的 $x(它最初在其上捕获错误/抛出错误)并再次使用相同的方法重试元素。它可能会导致无限循环,因此请保持任何重试阈值。

【讨论】:

我在迭代文本文件时使用了一个 foreach 循环,其中每一行都是“$x”(在上面的代码示例中)。这是迭代文本文档行的最简单的解决方案。我猜。【参考方案2】:

将 try 块放入自己的 while (true) 循环中,您可以在成功时 break

while (true) 
    try 
        ...
        break;
     catch (...) 
        ...
    

这会重试相同的操作,直到没有抛出异常。为了避免永远不会成功的操作的无限循环,您可以添加一个计数器,例如:

$tries = 0;
while ($tries < 10) 
    $tries++;
    try  ... 

【讨论】:

好的,所以如果我有 3 个元素,其中第二个元素会随机抛出错误:第一个元素会像往常一样通过 try 块并正常执行。第二次迭代将触发错误,因此在被捕获的块中回显错误并休眠 10 秒;然后通过try块继续相同的foreach迭代/元素(第二个元素)? 刚刚试了一下:效果很好。非常感谢! :) 现在有一个很小的机会,实际上会有一个错误导致脚本停止。在某个项目迭代 x 次后有什么方法可以继续?【参考方案3】:

一旦引发并捕获异常,就无法返回引发异常的代码块。不幸的是,没有技术上的可能性,您只有一个 try catch 块,您可以在其中捕获所有异常,然后确定它们是否重要(并停止执行脚本)或者异常不是真正的问题,并且您希望您的脚本表现得像如果没有例外。

我能给你的唯一解决办法是:

foreach($xx as $x) 
    try 
        //main code

        try 
            //first code that can cause an exception
            //you just want to continue after
         catch (Exception $e) 
            echo "Nothing wrong, just an exception " . $e->getMessage(), "\n";
        

        try 
            //second code that can cause an exception
            //a serious problem, you don't want to continue
         catch (Exception $e) 
            echo "This is a real problem " . $e->getMessage(), "\n";
            throw $e; //re-trowing exception
        

        //third code that can cause an exception

     catch (Exception $e) 
        //will catch exception from code 2 and 3 but not 1.

        echo 'Caught exception: ', $e->getMessage(), "\n";
        sleep(10);
    

顺便说一句。您所要求的不是通过使用异常来完成,而是在出现错误的情况下完成。如果发出错误信号,并且它是可恢复的,您可以为错误编写一个全局处理程序,并在该错误句柄中确定错误是否是您要关闭脚本的问题,或者只是记录它并返回脚本执行,就好像根本没有错误。但这是关于错误,而不是例外。

【讨论】:

对,所以在“主代码”、“第一个代码”和“第二个代码”中,我可以编写相同的代码.. 在@deceze 提供的解决方案中(工作正常)那里只是一个小缺陷:脚本真正停止工作/抛出异常的可能性很小...... @DoakCode 您可以编写相同的代码,但没有任何意义。如果您要执行的代码可能会引发您不关心的异常,则使用示例 first code 如果有代码引发异常并且您想对此做出反应(例如停止脚本),则使用 @ 987654323@ 示例,或者直接保留当前代码third code Jimmix - 确实如此。也许我太糟糕了,无法完全理解您的代码,或者它不适合我的情况。无论哪种方式,在我的情况下,我的代码可能会引发异常,即使解析的元素完全没问题并且下次会通过(由于 API 限制) - 因此需要重复。我无法让您的解决方案正常工作,而是使用@deceze 的方法来进行 while 循环(这也解决了我的最新问题,即如果发生“真正的问题”,while 循环会重试,例如仅 3 次)。我感谢您的所有建议 - 但 [at] deceze 找到了我的建议 正在寻找! @DoakCode 可能我错误地理解了你的意图,使用@deceze 解决方案你仍然会中断你的代码,并且在第一个异常之后让你在代码的第 20 行说你永远不会执行第 21 行, 22,以及所有其余代码,除非在第 20 行没有抛出异常,或者您将第 20 行放在 try-catch 中,如first code。但最终,您找到了适合您需求的有效解决方案是件好事。

以上是关于在 try-catch 块中继续当前迭代 | PHP的主要内容,如果未能解决你的问题,请参考以下文章

如何检查线程代码是不是在 try-catch 块中运行

java 在try-catch块中使用if语句不适用于JSoup

try-catch- finally块中, finally块唯一不执行的情况是什么?

当服务器在 try-catch 块中发送 422 时,axios 无法捕获错误

std::unique_ptr 取消引用异常未在 try-catch 块中捕获

在 Fragment 的地图中检测当前位置时遇到问题