PHP生成器:捕获异常和产量

时间:2017-01-10 18:28:48

标签: php generator

是否有可能在生成器中捕获异常而只是产生下一个值?我尝试过类似下面示例中的代码,但它会在异常时停止,并且不会将下一个值作为“预期”产生。

function generator(){
     foreach($aLotOfWork as $task){
       try {
         $promise = doSomethingThatCanFailBadly($task);

         yield $promise;
       } catch (Exception $e) {
         echo "oh.. there is an error, but I don't care and continue";
       }
     }
  }

恕我直言这不是(php: catch exception and continue execution, is it possible?)的重复,因为这个人只是想知道如何在php中捕获异常并继续。在我的情况下,我已经捕获所有异常,但生成器停止并且不按预期继续。

3 个答案:

答案 0 :(得分:1)

您的代码是正确的,它将捕获异常并继续,请查看:

$ cat so.php 
<?php

function doSomethingThatCanFailBadly($task) {
  if ($task == 3) {
    throw new Exception();
  }
  return $task;
}

function generator(){
     $aLotOfWork = array(1,2,3,4,5);
     foreach($aLotOfWork as $task){
       try {
         $promise = doSomethingThatCanFailBadly($task);

         yield $promise;
       } catch (Exception $e) {
         echo "oh.. there is an error, but I don't care and continue\n";
       }
     }
  }


foreach (generator() as $number) {
    echo "$number\n";
}
?>

$ php so.php 
1
2
oh.. there is an error, but I don't care and continue
4
5

查看错误堆栈跟踪。也许正在发生的事情是doSomethingThatCanFailBadly方法中的某些内容正在产生异常,但它也会抓住它并在die()exit()强制退出之前抓住了。在那种情况下,你无能为力。您可以使用register_shutdown_function并查看是否有帮助,但这开始看起来太乱了。

答案 1 :(得分:0)

您需要将生成器的输出保存到数组中,并且如果在单独生成期间抛出异常,并且通过正确的异常处理,它将无法进入数组。

在您的示例中,[-]ERROR: See Stack Trace java.lang.NullPointerException at Scraper.Appetizers.parseDocForTitles(Appetizers.java:35) at Scraper.Driver.main(Driver.java:25) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) 抛出异常,然后程序流进入doSomethingThatCanFailBadly分支。实际上catch实际上doSomethingThatCanFailBadly没有可以分配给$promise的返回值 - 所以此时没有什么可以产生的。

答案 2 :(得分:0)

@palako很好地解释了这个问题,但他并没有真正为我的案例提供解决方案。我使用这个生成器生成Promises,而消费者(Guzzle的EveryPromise-method)似乎停止了Exception。所以我用throw new SomeException('error message')替换了return RejectedPromise('error message')语句。

我必须承认这是一个非常特定于情境的解决方案,但您也可以在其他设置中执行类似操作:只返回一个对象而不是使用异常。