我有一个生成器,它将一组值传递给一个方法并生成结果。调用的方法可能会返回异常。当发生这种情况时,我希望异常通过调用生成器来处理异常的代码,然后继续循环生成器。
为了说明这一点,以下是生成 1
的生成器示例,抛出\Exception
,然后生成 3
/** @var \Generator $gen */
$gen = function () {
for ($i = 1; $i <= 3; $i++) {
if ($i == 2) {
throw new \Exception('Exception thrown for 2');
}
yield $i;
}
};
这是我尝试运行此代码的一个示例,以便我可以让它产生 3
$g = $gen();
var_export($g->current());
echo "\n";
try {
$g->next();
var_export($g->current());
echo "\n";
} catch (\Exception $e) {
echo $e->getMessage() . "\n";
}
try {
$g->next();
var_export($g->current());
echo "\n";
} catch (\Exception $e) {
echo $e->getMessage() . "\n";
}
以下是上述代码的输出。
1
Exception thrown for 2.
NULL
因此,对next()
的重复调用不执行任何操作,current()
将返回NULL
,我希望生成器继续超过异常,以便我可以获得 {{1 }}
答案 0 :(得分:2)
在生成器中抛出异常完全关闭它,这就是它在第三次迭代时返回“NULL”的原因。如果您在抛出异常后尝试$g->valid()
,则会得到false
作为结果。
您应该处理生成器内的异常,甚至可以使用$g->throw()
方法将它们放在生成器中。有关详细信息check the documentation
然而,您可以尝试实现的目标。您可以yield
例外,而不是投掷。这样你就不会关闭生成器,并且可以在外面处理异常。
试试这段代码:
$gen = function () {
for ($i = 1; $i <= 3; $i++) {
// If something wrong happens
if ($i == 2) {
// Instead throwing the exception yield it
// that way we don't close the generator
yield new \Exception('Exception thrown for 2');
} else {
yield $i;
}
}
};
用以下方法测试:
$g = $gen();
for ($i = 0; $i < 3; $i++) {
$current = $g->current();
// Instead of catching, check if the yielded value is Exception
if ($current instanceof \Exception) {
// Handle the exception directly
// or throw it with throw $current to handle it in normal try-catch block
echo $current->getMessage() . "\n";
} else {
echo $current . "\n";
}
$g->next();
}
给你结果:
1
Exception thrown for 2
3