Deferred.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. <?php
  2. namespace Http\Client\Common;
  3. use Http\Client\Exception;
  4. use Http\Promise\Promise;
  5. use Psr\Http\Message\ResponseInterface;
  6. /**
  7. * A deferred allow to return a promise which has not been resolved yet.
  8. */
  9. class Deferred implements Promise
  10. {
  11. private $value;
  12. private $failure;
  13. private $state;
  14. private $waitCallback;
  15. private $onFulfilledCallbacks;
  16. private $onRejectedCallbacks;
  17. public function __construct(callable $waitCallback)
  18. {
  19. $this->waitCallback = $waitCallback;
  20. $this->state = Promise::PENDING;
  21. $this->onFulfilledCallbacks = [];
  22. $this->onRejectedCallbacks = [];
  23. }
  24. /**
  25. * {@inheritdoc}
  26. */
  27. public function then(callable $onFulfilled = null, callable $onRejected = null)
  28. {
  29. $deferred = new self($this->waitCallback);
  30. $this->onFulfilledCallbacks[] = function (ResponseInterface $response) use ($onFulfilled, $deferred) {
  31. try {
  32. if (null !== $onFulfilled) {
  33. $response = $onFulfilled($response);
  34. }
  35. $deferred->resolve($response);
  36. } catch (Exception $exception) {
  37. $deferred->reject($exception);
  38. }
  39. };
  40. $this->onRejectedCallbacks[] = function (Exception $exception) use ($onRejected, $deferred) {
  41. try {
  42. if (null !== $onRejected) {
  43. $response = $onRejected($exception);
  44. $deferred->resolve($response);
  45. return;
  46. }
  47. $deferred->reject($exception);
  48. } catch (Exception $newException) {
  49. $deferred->reject($newException);
  50. }
  51. };
  52. return $deferred;
  53. }
  54. /**
  55. * {@inheritdoc}
  56. */
  57. public function getState()
  58. {
  59. return $this->state;
  60. }
  61. /**
  62. * Resolve this deferred with a Response.
  63. */
  64. public function resolve(ResponseInterface $response)
  65. {
  66. if (self::PENDING !== $this->state) {
  67. return;
  68. }
  69. $this->value = $response;
  70. $this->state = self::FULFILLED;
  71. foreach ($this->onFulfilledCallbacks as $onFulfilledCallback) {
  72. $onFulfilledCallback($response);
  73. }
  74. }
  75. /**
  76. * Reject this deferred with an Exception.
  77. */
  78. public function reject(Exception $exception)
  79. {
  80. if (self::PENDING !== $this->state) {
  81. return;
  82. }
  83. $this->failure = $exception;
  84. $this->state = self::REJECTED;
  85. foreach ($this->onRejectedCallbacks as $onRejectedCallback) {
  86. $onRejectedCallback($exception);
  87. }
  88. }
  89. /**
  90. * {@inheritdoc}
  91. */
  92. public function wait($unwrap = true)
  93. {
  94. if (self::PENDING === $this->state) {
  95. $callback = $this->waitCallback;
  96. $callback();
  97. }
  98. if (!$unwrap) {
  99. return;
  100. }
  101. if (self::FULFILLED === $this->state) {
  102. return $this->value;
  103. }
  104. throw $this->failure;
  105. }
  106. }