Exceptions
一般来说,Async遵循这种模式:
- 调用一个async函数
- 得到一个awaitable back
await
the awaitable得到结果
但是,有时Async函数可能会引发异常。好消息是,当您await
the awaitable的时候,Exception版本的代码将抛出同一个Exception对象。
<?hh
namespace Hack\UserDocumentation\Async\Exceptions\Examples\BasicException;
async function exception_thrower(): Awaitable<void> {
throw new \Exception("Return exception handle");
}
async function basic_exception(): Awaitable<void> {
// the handle does not throw, but result will be an Exception objection.
// Remember, this is the same as:
// $handle = exception_thrower();
// await $handle;
await exception_thrower();
}
\HH\Asio\join(basic_exception());
Output
Fatal error: Uncaught exception 'Exception' with message 'Return exception handle' in /data/users/joelm/user-documentation/guides/hack/22-async/03-exceptions-examples/basic-exception.php:6
Stack trace:
#0 /data/users/joelm/user-documentation/guides/hack/22-async/03-exceptions-examples/basic-exception.php(14): Hack\UserDocumentation\Async\Exceptions\Examples\BasicException\exception_thrower()
#1 /data/users/joelm/user-documentation/guides/hack/22-async/03-exceptions-examples/basic-exception.php(17): Hack\UserDocumentation\Async\Exceptions\Examples\BasicException\basic_exception()
#2 {main}
使用基本的实用功能v()
要么m()
将忽略任何成功的等待结果,只是抛出一个等待结果的异常,如果其中一个结果是一个Exception。
<?hh
namespace Hack\UserDocumentation\Async\Exceptions\Examples\MultipleAwaitable;
async function exception_thrower(): Awaitable<void> {
throw new \Exception("Return exception handle");
}
async function non_exception_thrower(): Awaitable<int> {
return 2;
}
async function multiple_waithandle_exception(): Awaitable<void> {
$handles = [exception_thrower(), non_exception_thrower()];
// You will get a fatal error here with the exception thrown
$results = await \HH\Asio\v($handles);
// This won't happen
var_dump($results);
}
\HH\Asio\join(multiple_waithandle_exception());
Output
Fatal error: Uncaught exception 'Exception' with message 'Return exception handle' in /data/users/joelm/user-documentation/guides/hack/22-async/03-exceptions-examples/multiple-awaitable-exception.php:6
Stack trace:
#0 /data/users/joelm/user-documentation/guides/hack/22-async/03-exceptions-examples/multiple-awaitable-exception.php(14): Hack\UserDocumentation\Async\Exceptions\Examples\MultipleAwaitable\exception_thrower()
#1 /data/users/joelm/user-documentation/guides/hack/22-async/03-exceptions-examples/multiple-awaitable-exception.php(21): Hack\UserDocumentation\Async\Exceptions\Examples\MultipleAwaitable\multiple_waithandle_exception()
#2 {main}
为了解决这个问题,并获得成功的结果,我们可以使用所谓的效用函数HH\Asio\wrap()
。它需要等待并返回预期结果或异常(如果被抛出)。它给出的例外是类型ResultOrExceptionWrapper
。
namespace HH\Asio {
interface ResultOrExceptionWrapper<T> {
public function isSucceeded(): bool;
public function isFailed(): bool;
public function getResult(): T;
public function getException(): \Exception;
}
}
以上面的例子和使用包装机制,这就是代码的样子:
<?hh
namespace Hack\UserDocumentation\Async\Exceptions\Examples\Wrapping;
async function exception_thrower(): Awaitable<void> {
throw new \Exception();
}
async function non_exception_thrower(): Awaitable<int> {
return 2;
}
async function wrapping_exceptions(): Awaitable<void> {
$handles = [\HH\Asio\wrap(exception_thrower()),
\HH\Asio\wrap(non_exception_thrower())];
// Since we wrapped, the results will contain both the exception and the
// integer result
$results = await \HH\Asio\v($handles);
var_dump($results);
}
\HH\Asio\join(wrapping_exceptions());
Output
object(HH\Vector)#11 (2) {
[0]=>
object(HH\Asio\WrappedException)#4 (1) {
["exception":"HH\Asio\WrappedException":private]=>
object(Exception)#2 (7) {
["message":protected]=>
string(0) ""
["string":"Exception":private]=>
string(0) ""
["code":protected]=>
int(0)
["file":protected]=>
string(104) "/data/users/joelm/user-documentation/guides/hack/22-async/03-exceptions-examples/wrapping-exceptions.php"
["line":protected]=>
int(8)
["trace":"Exception":private]=>
array(2) {
[0]=>
array(4) {
["file"]=>
string(104) "/data/users/joelm/user-documentation/guides/hack/22-async/03-exceptions-examples/wrapping-exceptions.php"
["line"]=>
int(16)
["function"]=>
string(75) "Hack\UserDocumentation\Async\Exceptions\Examples\Wrapping\exception_thrower"
["args"]=>
array(0) {
}
}
[1]=>
array(4) {
["file"]=>
string(104) "/data/users/joelm/user-documentation/guides/hack/22-async/03-exceptions-examples/wrapping-exceptions.php"
["line"]=>
int(24)
["function"]=>
string(77) "Hack\UserDocumentation\Async\Exceptions\Examples\Wrapping\wrapping_exceptions"
["args"]=>
array(0) {
}
}
}
["previous":"Exception":private]=>
NULL
}
}
[1]=>
object(HH\Asio\WrappedResult)#7 (1) {
["result":"HH\Asio\WrappedResult":private]=>
int(2)
}
}