codecamp

Exceptions

一般来说,Async遵循这种模式:

  • 调用一个async函数
  • 得到一个awaitable back
  • awaitthe awaitable得到结果

但是,有时Async函数可能会引发异常。好消息是,当您awaitthe 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)
  }
}
Awaitable
Async Blocks
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }