[英]How to catch exception thrown from a generator and resume iteration?
我有一个生成器,它将一组值传递给一个方法并产生结果。 被调用的方法可能会返回异常。 发生这种情况时,我希望异常落入调用生成器处理异常的代码,然后继续循环生成器。
为了说明这一点,下面是一个生成器的例子,它会产生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
,我希望生成器继续通过 Exception 以便我可以获得3
。
在生成器中抛出异常会完全关闭它,这就是它在第三次迭代时返回“NULL”的原因。 如果在抛出异常后尝试$g->valid()
,结果将是false
。
生成器内部抛出的所有异常也应该在内部捕获和处理,您甚至可以使用$g->throw()
方法将它们从外部抛出到生成器中进行处理。 有关更多信息,请查看文档
但是,您尝试实现的目标是可能的。 您可以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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.