             urlReq.httpBody = try request.body?.encode(self.defaultEncoder)
         } catch {
             // We were unable to make the request
-            handleResult(.failure(.unencodableRequest(error: error)))
+            self.handleRequestResult(.failure(.unencodableRequest(error: error)), endpointName: endpointName, completesOn: completionQueue, completion: completion)
             return
         }
+        let reqDecoder = request.decoder
         let defaultDecoder = self.defaultDecoder
-        let task = self.urlSession.dataTask(with: urlReq) { (data, urlResponse, error) in
+        let task = self.urlSession.dataTask(with: urlReq) { [weak self] (data, urlResponse, error) in
             if let data = data, let httpResponse = urlResponse as? HTTPURLResponse {
                 if (200..<300).contains(httpResponse.statusCode) {
                     do {
-                        let successResponse = try request.decoder.decode(data, defaultDecoder)
+                        let successResponse = try reqDecoder.decode(data, defaultDecoder)
                         // Successfully decoded the expected ResponseType!
-                        handleResult(.success((successResponse, httpResponse)))
+                        self?.handleRequestResult(.success((successResponse, httpResponse)), endpointName: endpointName, completesOn: completionQueue, completion: completion)
                         return
                     } catch let decodeError {
                         // Unable to decode the expected ResponseType.
-                        handleResult(.failure(.decode(error: decodeError, data: data)))
+                        self?.handleRequestResult(.failure(.decode(error: decodeError, data: data)), endpointName: endpointName, completesOn: completionQueue, completion: completion)
                         return
                     }
                 } else if let errorResponse = try? JSONDecoder().decode(APIError.ServerResponse.self, from: data) {
                     // We got a specific error object in the server's response.
-                    handleResult(.failure(.server(errorResponse, httpResponse: httpResponse)))
+                    self?.handleRequestResult(.failure(.server(errorResponse, httpResponse: httpResponse)), endpointName: endpointName, completesOn: completionQueue, completion: completion)
                     return
                 } else if let stringResponse = String(data: data, encoding: .utf8) {
                     // We got some error data in the server's response, but we cant decode it.
-                    handleResult(.failure(.undecodableServer(stringResponse, httpResponse: httpResponse)))
+                    self?.handleRequestResult(.failure(.undecodableServer(stringResponse, httpResponse: httpResponse)), endpointName: endpointName, completesOn: completionQueue, completion: completion)
                     return
                 }
             }
             
             if let error = error {
                 // We got a system networking error.
-                handleResult(.failure(.network(error: error, urlResponse: urlResponse)))
+                self?.handleRequestResult(.failure(.network(error: error, urlResponse: urlResponse)), endpointName: endpointName, completesOn: completionQueue, completion: completion)
                 return
             } else {
                 // The request failed for some unknown reason.
-                handleResult(.failure(.failedRequest(urlResponse: urlResponse)))
+                self?.handleRequestResult(.failure(.failedRequest(urlResponse: urlResponse)), endpointName: endpointName, completesOn: completionQueue, completion: completion)
                 return
             }
         }
         task.resume()
+    }
+    
+    fileprivate func handleRequestResult<ResponseType>(_ result: Result<(ResponseType, HTTPURLResponse), APIError>, endpointName: String, completesOn completionQueue: DispatchQueue, completion: @escaping (Result<ResponseType, APIError>) -> Void) {
+        switch result {
+        case let .success((response, httpResponse)):
+            // tell any listeners about the http response
+            self.callResponseListeners(
+                endpointName: endpointName,
+                result: .success(httpResponse)
+            )
+            
+            // complete with success!
+            completionQueue.async {
+                completion(.success(response))
+            }
+        case let .failure(error):
+            
+            // tell any listeners about the error
+            self.callResponseListeners(
+                endpointName: endpointName,
+                result: .failure(error)
+            )
+            
+            // complete with failure :(
+            completionQueue.async {
+                completion(.failure(error))
+            }
+        }
     }
 }
 

    // MARK: - Private funcs
    
    private func callResponseListeners(endpointName: String, result: Result<HTTPURLResponse, APIError>) {
        self.responseListeners.forEach({ listener in
            listener.queue.async {
                listener.callback(endpointName, result)
            }
        })
    }
}


        completesOn completionQueue: DispatchQueue,
        completion: @escaping (Result<ResponseType, APIError>) -> Void
    ) {
        let endpointName = request.endpoint
        var endpointURL = self.baseURL.appendingPathComponent(endpointName)
        let headers = self.clientHeaders
        
        // add the request's queryParams to the url
