代码之家  ›  专栏  ›  技术社区  ›  Alana Storm

PHP生成器能否从未捕获的异常中恢复?

  •  1
  • Alana Storm  · 技术社区  · 6 年前

    在PHP中考虑这个简单的生成器函数。

    function createAGenerator() {
        echo 'Before First Yield',"\n";
        yield 'First Yield';
        echo 'Before Second Yield',"\n";
        yield 'Second Yield';
        echo 'Before Third Yield',"\n";
        yield 'Third Yield';
    }
    

    如果我用生成器对象的 throw 方法

    $generator = createAGenerator();
    try {
        $generator->throw(new Exception('Throwing into a Generator'));
    } catch(Exception $e) {
        echo 'Caught Exception: ', $e->getMessage(), "\n";
    }
    echo 'Resuming Main Program Execution',"\n";
    

    生成器函数将重新抛出异常以供我捕获。这一切都如我所料。

    然而,我的发电机现在似乎永远卡住了。如果我想继续 next 屈服,或 send 如果在中有一个新值,则生成器似乎刚刚返回 NULL .例如,以下程序

    <?php
    function createAGenerator() {
        echo 'Before First Yield',"\n";
        yield 'First Yield';
        echo 'Before Second Yield',"\n";
        yield 'Second Yield';
        echo 'Before Third Yield',"\n";
        yield 'Third Yield';
    }
    
    $generator = createAGenerator();
    try {
        $generator->throw(new Exception('Throwing into a Generator'));
    } catch(Exception $e) {
        echo 'Caught Exception: ', $e->getMessage(), "\n";
    }
    echo 'Resuming Main Program Execution',"\n";
    
    var_dump($generator->send('Some Value'));
    var_dump($generator->current());
    var_dump($generator->next());
    var_dump($generator->current());
    

    返回以下输出。

    Before First Yield
    Caught Exception: Throwing into a Generator
    Resuming Main Program Execution
    NULL
    NULL
    NULL
    NULL
    

    发电机有办法从中恢复吗?或者,生成器中的未捕获异常是否会“破坏”该生成器的当前实例?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Evert    6 年前

    当抛出异常时,生成器将直接跳到函数末尾。这正是常规函数中发生的情况,如果该函数调用了引发异常的东西。

    你的两个选择是:

    1. 在发电机中捕捉(或最终使用)。
    2. 一点也不扔

    抛出异常并将其用作“临时”消息传递系统,但恢复正常操作的想法有点奇怪。这听起来有点滥用例外。也许你正在努力实现的目标可以毫无例外地实现。

    如果您试图对一个包含多个步骤的操作进行建模,并且每个步骤都可能失败或成功,那么一个选项可能是只生成异常,而不抛出它。