异常: 重新加入Async

重新加入Async,修改continuation的签名,加入异常参数:

  1. <?php
  2. interface Async
  3. {
  4. // continuation :: (mixed $r, \Exception $ex) -> void
  5. public function begin(callable $continuation);
  6. }
  7. final class AsyncTask implements Async
  8. {
  9. public function next($result = null, $ex = null)
  10. {
  11. try {
  12. // ...
  13. if ($this->gen->valid()) {
  14. if ($value instanceof \Generator) {
  15. $value = new self($value);
  16. }
  17. if ($value instanceof Async) {
  18. $cc = [$this, "next"];
  19. $value->begin($cc);
  20. } else {
  21. $this->next($value, null);
  22. }
  23. } else {
  24. $cc = $this->continuation;
  25. $cc($result, null);
  26. }
  27. } catch (\Exception $ex) {
  28. // ...
  29. }
  30. }
  31. }
  1. <?php
  2. $trace = function($r, $ex) {
  3. if ($ex instanceof \Exception) {
  4. echo "cc_ex:" . $ex->getMessage(), "\n";
  5. }
  6. };
  7. class AsyncException implements Async
  8. {
  9. public function begin(callable $cc)
  10. {
  11. swoole_timer_after(1000, function() use($cc) {
  12. $cc(null, new \Exception("timeout"));
  13. });
  14. }
  15. }
  16. function newSubGen()
  17. {
  18. yield 0;
  19. $async = new AsyncException();
  20. yield $async;
  21. }
  22. function newGen($try)
  23. {
  24. $start = time();
  25. try {
  26. $r1 = (yield newSubGen());
  27. } catch (\Exception $ex) {
  28. // 捕获subgenerator抛出的异常
  29. if ($try) {
  30. echo "catch:" . $ex->getMessage(), "\n";
  31. } else {
  32. throw $ex;
  33. }
  34. }
  35. echo time() - $start, "\n";
  36. }
  37. // 内部try-catch异常
  38. $task = new AsyncTask(newGen(true));
  39. $task->begin($trace);
  40. // output:
  41. // catch:timeout
  42. // 1
  43. // 异常传递至AsyncTask的最终回调
  44. $task = new AsyncTask(newGen(false));
  45. $task->begin($trace);
  46. // output:
  47. // cc_ex:timeout