Skip to content

FR: Ability to cancel Function call #6077

Open
@mozeryansky

Description

@mozeryansky

Feature proposal

  • Firebase Component: Functions

In my app I am using function calls to download lots of data. I queue up many requests and process these. However, if my user chooses to logout while the networking is happening I would like to stop all the requests. There does not seem to be a way to cancel all running function calls.

Right now I effectively cancel the request by having the completion block call an internal completion block. When I call "cancel" I change the internal completion block to nil and call the original block with an error of "cancelled". The works for my app, but underneath the request is still occurring. (Example below for those who want my solution)

I see that Firebase Functions use a GTMSessionFetcher to make a network request using NSURLSession which creates a NSURLSessionTask, and NSURLSessionTask's have a cancel method on them.

What would it take to have a "cancelAllCalls" function? What is the current guidance on achieving this?

==== Cancelling Example ====

typealias CompletionBlock = (Result<Any, Error>) -> Void
var activeCalls = [String: CompletionBlock]()

func call(_ functionName: String, data: Any?, completion: @escaping CompletionBlock) {
    let id = UUID().uuidString
    let wrappedCompletion: CompletionBlock = { result in
        self.activeCalls[id]?(result)
        self.activeCalls[id] = nil
    }

    activeCalls[id] = completion

    functions.httpsCallable(functionName).call(data) { (result, error) in
        if let error = error {
            wrappedCompletion(.failure(error))
            return
        }
        guard let result = result else {
            wrappedCompletion(.failure(FunctionsError.invalidData))
            return
        }
        wrappedCompletion(.success(result.data))
    }
}

func cancelAllCalls() {
    for (id, result) in activeCalls {
        result(.failure(FunctionsError.cancelled))
        self.activeCalls[id] = nil
    }
}

^ My actual solution changes the completion handles to keep track of the remaining calls, and uses queues. But that's the gist of it.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions