PHP Generator::throw() 方法
PHP Generator::throw()
方法用于手动引发生成器的一个异常。
( PHP 5 >= 5.5.0, PHP 7 )
这个方法就有意思了,使用 Generator::throw()
方法,我们可以在外部生成一个异常,并将该已成发送给生成器,生成器会在下次遇到 yield
语句时触发这个异常。
方法原型
PHP Generator::throw()
方法的原型如下
public mixed Generator::throw ( Throwable $exception )
从原型中可以看出,该方法接收一个异常 $exception
,并将异常发送给生成器,并继续执行生成器。(因为生成器需要下次遇到 yield 时才会触发这个异常 )。
这个方法的行为和在生成器内部使用 throw $exception
语句替换当前 yield 表达式时的行为相同。
如果在调用此方法时生成器已关闭,则异常将在调用者的上下文中抛出。
参数说明
参数 | 说明 |
---|---|
$exception | 要发送给生成器的异常 |
返回值
该方法返回已经 yield 的值。
你不是不很奇怪为什么还会返回一个值? 难道不是调用就会立即触发异常么 ?
前面章节我忘记说了,生成器看起来是在另一个线程中异步执行的代码。一旦执行,如果要停下来,只能是再次碰到 yield 语句。
范例一
简单的生成一个异常,并将该异常发送给生成器
<?php function gen() { echo "Foo\n"; try { yield; } catch (Exception $e) { echo "Exception: {$e->getMessage()}\n"; } echo "Bar\n"; } $gen = gen(); $gen->throw(new Exception('Test'));
运行结果如下
Foo Exception: Test Bar
上面这段代码,当调用 gen()
创建一个生成器时并不会执行任何生成器内的函数。直到调用 $gen->throw(new Exception('Test'));
将一个异常发送给这个生成器。
因为该函数同时会触发生成器的执行,所以,就会开始输出 Foo
,但运行到 yield
时发现就要抛出一个异常,于是就会抛出一个异常,抛出的异常会被 try catch
捕获到,于是会输出 Exception: Test
,然后函数继续执行,就会输出 Bar
范例二
在上面这个范例中,yield 语句并没有生成一个值,我们看看如果生成了一个值的会是什么结果
<?php function gen() { echo "Foo\n"; for ( $i = 0; $i < 10; $i++ ) { try { echo $i,"\n"; yield $i; } catch (Exception $e) { echo "Exception: {$e->getMessage()}\n"; } } echo "Bar\n"; } $gen = gen(); $ret = $gen->throw(new Exception('Test')); echo $ret,"\n";
运行结果如下
Foo 0 Exception: Test 1 1
是不是对执行结果感到很疑惑 ?
首先,要记牢一件事:生成器只有运行到一个 yield 语句时才会停止执行。
所以当调用 $gen->throw(new Exception('Test'));
会触发生成器的执行,这会一路输出 Foo
和 0
。但是,当执行到 yield 0
时需要触发异常,所以这时候 yield 语句并不会暂停执行,而是继续执行,直到捕获异常,输出 Exception: Test
,然后进行下一次迭代,输出 1
然后碰到 yield 1
,这时候就会暂停执行了,因为 yield 1
的返回就是 1
,所以,结果就像输出的那样了。