public function receive($keepWaiting = false)
    {
        $this->shouldBeConnected();

        $type = $this->getType($keepWaiting);
        if (!array_key_exists($type, $this->responseHandlers)) {
            throw new ResponseException("Don't know how to handle a response of type {$type}");
        }

        $responseHandlerClass = $this->responseHandlers[$type];
        $responseHandler = new $responseHandlerClass($this->getData());
        $responseHandler->setReader(function ($bytes) {
            return fread($this->socket, $bytes);
        });
        $responseHandler->setReceiver(function () use ($keepWaiting) {
            return $this->receive($keepWaiting);
        });
        $response = $responseHandler->parse();

        /**
         * If Disque returned an error, raise it in form of an exception
         * @see Disque\Connection\Response\ErrorResponse::parse()
         */
        if ($response instanceof ResponseException) {
            throw $response;
        }

        return $response;
    }