protected function sendAsync(
        $method,
        array $headers,
        array $queryParams,
        array $postParameters,
        $path,
        $expected = Resources::STATUS_OK,
        $body = Resources::EMPTY_STRING,
        ServiceOptions $serviceOptions = null
    ) {
        if ($serviceOptions == null) {
            $serviceOptions = new ServiceOptions();
        }
        $this->addOptionalQueryParam(
            $queryParams,
            Resources::QP_TIMEOUT,
            $serviceOptions->getTimeout()
        );

        $request = $this->createRequest(
            $method,
            $headers,
            $queryParams,
            $postParameters,
            $path,
            $serviceOptions->getLocationMode(),
            $body
        );

        $client = $this->client;

        $middlewareStack = $this->createMiddlewareStack($serviceOptions);

        $sendAsync = function ($request, $options) use ($client) {
            return $client->sendAsync($request, $options);
        };

        $handler = $middlewareStack->apply($sendAsync);

        $requestOptions =
            $this->generateRequestOptions($serviceOptions, $handler);

        if ($request->getMethod() == 'HEAD') {
            $requestOptions[Resources::ROS_DECODE_CONTENT] = false;
        }

        $promise = \call_user_func($handler, $request, $requestOptions);

        return $promise->then(
            function ($response) use ($expected, $requestOptions) {
                self::throwIfError(
                    $response,
                    $expected
                );

                return self::addLocationHeaderToResponse(
                    $response,
                    $requestOptions[Resources::ROS_LOCATION_MODE]
                );
            },
            function ($reason) use ($expected) {
                if (!($reason instanceof RequestException)) {
                    throw $reason;
                }
                $response = $reason->getResponse();
                if ($response != null) {
                    self::throwIfError(
                        $response,
                        $expected
                    );
                } else {
                    //if could not get response but promise rejected, throw reason.
                    throw $reason;
                }
                return $response;
            }
        );
    }