/** * Request asynchronously using the current HTTP client, preparing the * success and exception callbacks to transfer results in. * * @param string $method HTTP method * @param callable $uriCallable Must return array of uri parts * @param callable $optionsCallable Must return array of request options * @param callable $onFulfilled Option callback to chain on fulfillment * @param callable $onRejected Option callback to chain on rejection * * @return PromiseInterface */ protected function requestAsync($method, callable $uriCallable = null, callable $optionsCallable = null, callable $onFulfilled = null, callable $onRejected = null) { // clear previous responses and settle any async operation $this->clearResponse(); // define request options $uri = null; $options = []; try { // uri if ($uriCallable) { $uri = (array) $uriCallable($this); // sanitize uri parts, RFC 3986 $uri = implode('/', array_map('rawurlencode', $uri)); } // options if ($optionsCallable) { $options = (array) $optionsCallable($this); // safely build query string if (isset($options['query']) && is_array($options['query'])) { $options['query'] = http_build_query($options['query'], null, '&', PHP_QUERY_RFC3986); } } } catch (MissingPropertyException $e) { $this->setException($e); return new RejectedPromiseException($this->getReasonPhrase(), $this); } // enforce http exceptions $options['http_errors'] = true; // request $promise = $this->getHttpClient()->requestAsync($method, $uri, $options); $self = $this; $this->_promise = $promise->then(static function (ResponseInterface $response) use($self) { // clear out $self->_promise = null; // set response $self->transferResponseData($response); // return the item itself return $self; }, static function (RequestException $e) use($self) { // clear out $self->_promise = null; // set exception $self->setException($e); // set response, if there is one if ($e->hasResponse()) { $self->transferResponseData($e->getResponse()); // honor the Orchestrate error messages if (!empty($self->_bodyArray['message'])) { $self->_reasonPhrase = $self->_bodyArray['message']; } } // return exception, with possibility to get the item back return new RejectedPromise(new RejectedPromiseException($self->getReasonPhrase(), $self)); }); // chain if ($onFulfilled || $onRejected) { $this->_promise = $this->_promise->then($onFulfilled, $onRejected); } return $this->_promise; }
/** * {@inheritdoc} */ public function then(callable $onFulfilled = null, callable $onRejected = null) { return new static($this->promise->then($onFulfilled, $onRejected), $this->request); }
/** * This method registers an onFulfilled and an onRejected handler to proxy the result to the deferred * * Note: The Guzzle\Promise will only be resolved when the global task queue `run` is invoked: * This task queue MUST be run in an event loop in order for promises to be * settled asynchronously. * * <code> * while ($eventLoop->isRunning()) { * GuzzleHttp\Promise\queue()->run(); * } * </code> * * @param Deferred $deferred * @param PromiseInterface $promise */ private function resolveOrRejectDeferredAsync(Deferred $deferred, PromiseInterface $promise) { $promise->then(function (ResponseInterface $response) use($deferred) { try { $payload = $this->getPayloadFromResponse($response); $deferred->resolve($payload); } catch (\Exception $e) { $deferred->reject($e); } }, function ($reason) use($deferred) { $deferred->reject($reason); }); }
private function withTracking(PromiseInterface $promise, $uri) { return $promise->then(function (ResponseInterface $response) use($uri) { // Note that we are pushing to the front of the list as this // would be an earlier response than what is currently present // in the history header. $header = $response->getHeader(self::HISTORY_HEADER); array_unshift($header, $uri); return $response->withHeader(self::HISTORY_HEADER, $header); }); }