【问题标题】:Can a PHP Generator Recover From an Uncaught Exception?PHP 生成器可以从未捕获的异常中恢复吗?
【发布时间】:2019-04-15 14:55:23
【问题描述】:

考虑一下 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

有没有办法让生成器从中恢复?还是生成器中未捕获的异常“破坏”了当前的生成器实例?

【问题讨论】:

  • 你想用这个实现什么 - 向生成器发出信号或只是看看它为什么会中断?
  • @NigelRen 感谢您的回复。对于这个问题,我没有任何特别的目标。相反,我试图更好地理解所有可能情况下的生成器代码执行情况。
  • 只是您使用-&gt;send(),但不要获取该值,使用$ret = yield 'First Yield'; 将允许您针对某些特定情况向生成器发出“信号”。

标签: php generator


【解决方案1】:

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

您的两个选择是:

  1. 在生成器中捕获它(或最终使用)。
  2. 根本不扔

抛出异常并将其用作“临时”消息传递系统但恢复正常操作的想法有点奇怪。这听起来有点像滥用异常。也许您想要实现的目标可以在不引发异常的情况下完成。

如果您尝试对包含多个步骤且每个步骤都可能单独失败或成功的操作进行建模,则一种选择可能是只产生异常而不抛出它。

【讨论】:

  • 感谢您的回复!为了全面披露,我并不想在这里实现任何特定目标,我只是想了解生成器方法提供的所有情况下进出生成器的代码执行情况,包括奇怪的-我扔:)
  • @AlanStorm 如果您有使用现代 javascript 的经验,假装 yield 是“等待”可能会有所帮助。
猜你喜欢
  • 2011-12-28
  • 2018-11-22
  • 1970-01-01
  • 2014-01-27
  • 1970-01-01
  • 1970-01-01
  • 2011-07-15
  • 2017-01-04
相关资源
最近更新 更多