为什么在PHP中使用Generator :: throw会在抛出后忽略产生的值

时间:2018-07-17 13:10:43

标签: php generator throw

我试图理解为什么Generator::throw使调用者在Exception中捕获Generator之后不接收值。

<?php

class moo
{
    public function run()
    {
        $generator = $this->getIterator();
        foreach ($generator as $item) {
            try {
                error_log("PROCESS: {$item}");

                if ($item % 2 === 0) {
                    error_log("throwing InvalidArgumentException $item");
                    throw new InvalidArgumentException($item);
                }
            } catch (Throwable $e) {
                $generator->throw($e);
            }
        }
    }

    private function getIterator()
    {
        foreach (range(1, 6) as $item) {
            try {
                yield $item;

            } catch (Throwable $e) {

                $class = get_class($e);
                error_log("GOT[$class] in generator: {$e->getMessage()}");
            }
        }
    }
}

$m = new moo();
$m->run();

上面的代码打印:

PROCESS: 1
PROCESS: 2
throwing InvalidArgumentException 2
GOT[InvalidArgumentException] in generator: 2
PROCESS: 4
throwing InvalidArgumentException 4
GOT[InvalidArgumentException] in generator: 4
PROCESS: 6
throwing InvalidArgumentException 6
GOT[InvalidArgumentException] in generator: 6

run方法中循环不会看到3和5之类的值

文档没有表明这是预期的行为

  

将异常引发到生成器中,并继续执行   发电机。行为将与当前收益率相同   表达式被替换为throw $ exception语句。

这是php中的错误吗?

2 个答案:

答案 0 :(得分:2)

当您引用PHP文档时:

  

...行为与当前 yield表达式相同   被替换为throw $ exception语句。

这是预期的行为。

答案 1 :(得分:1)

Paul CrovellaŁukasz Jakubek所述,该值“丢失”到返回值$generator->throw()中。

我已经创建了一个项目,如果将Generator包裹起来,则yield值将按顺序出现在yield消费者:https://github.com/glensc/ThrowableGenerator

编辑:还添加了:: send()包装器:https://github.com/glensc/ThrowableGenerator/releases/tag/1.1.0