/**
  * executeAsync
  *
  * Execute an operation asynchronously.
  *
  * @param \ArtaxServiceBuilder\Operation $operation The operation to perform
  * @param callable $callback The callback to call on completion/response. The
  * signature of the method should be:
  * function(
  *     \Exception $error = null, // null if no error 
  *     $parsedData = null, //The parsed operation data i.e. same type as
  * responseClass of the operation.
  *     \Amp\Artax\Response $response = null //The response received or null if the
  * request completely failed.
  * )
  * @return \Amp\Promise A promise to resolve the call at some time.
  */
 public function executeAsync(\Amp\Artax\Request $request, \ArtaxServiceBuilder\Operation $operation, callable $callback)
 {
     $originalRequest = clone $request;
     $cachingHeaders = $this->responseCache->getCachingHeaders($request);
     $request->setAllHeaders($cachingHeaders);
     $promise = $this->client->request($request);
     $promise->when(function (\Exception $error = null, Response $response = null) use($originalRequest, $callback, $operation) {
         if ($response) {
             $operation->setResponse($response);
             $operation->setOriginalResponse($response);
         }
         if ($error) {
             $callback($error, null, null);
             return;
         }
         if ($operation->shouldResponseBeCached($response)) {
             $this->responseCache->storeResponse($originalRequest, $response);
         }
         if ($operation->shouldUseCachedResponse($response)) {
             $cachedResponse = $this->responseCache->getResponse($originalRequest);
             if ($cachedResponse) {
                 $response = $cachedResponse;
                 $operation->setResponse($response);
             }
         }
         $responseException = $operation->translateResponseToException($response);
         if ($responseException) {
             $callback($responseException, null, $response);
             return;
         }
         if ($operation->shouldResponseBeProcessed($response)) {
             try {
                 $parsedResponse = $operation->processResponse($response);
                 $callback(null, $parsedResponse, $response);
             } catch (\Exception $e) {
                 $exception = new ProcessResponseException("Exception parsing response: " . $e->getMessage(), 0, $e);
                 $callback($exception, null, $response);
             }
         } else {
             $callback(null, null, $response);
         }
     });
     return $promise;
 }