Search code examples
iosswiftpromisekit

Polling for a async task and then waiting for either 1 success or all response rejected


PromiseKit version: 4.0

Xcode version: 8.3.2

I have recently started using PromiseKit.

Actually, I am creating a polling HTTP request which in returns gives "completed" or "notCompleted".

I have to keep making HTTP calls after every 1 secs for a duration of 5 seconds.

What I need to achieve is if any 1 call gives me completed status I will return fulfilled("completed"). But if all of my requests gives me a response of "notCompleted", I need to return reject("notCompleted")

return Promise<T> { fulfilled, reject
let timer1 =  Timer.scheduledTimer(withTimeInterval: TimeInterval(1), repeats: true) { timer in
    pArr.append(Promise<T> { f, r in

        doSomeAsyncTask { T in
            if success {
                f(T)
                fulfilled(T)
                timer.invalidate()
            } else {
                 r(ErrorNotCompleted)
            }
        }

        // timeout option
        _ = after(interval: TimeInterval(15)).then(execute: { () -> Void in
            reject(timeoutForConfirmation)
        })
    })
    }


Timer.scheduledTimer(withTimeInterval: TimeInterval(5), repeats: false) { timer in
    timer1.invalidate()
    timer.invalidate()
    when(resolved: pArr).then { results in
        let count = results.filter({ result -> Bool in
             return result.boolValue
        }).count

        if count == 0 {
            // TODO: then reject here
            reject(ErrorNotCompleted)
        }

        }.catch { error in
            print(error)
    }
}

} 
timer1.fire()

How can I achieve this?

Is there a better way to write the above code in PromiseKit.


Solution

  • Here is a way to do a basic loop with Promises... It's from my gist: https://gist.github.com/dtartaglia/2b19e59beaf480535596

    I think all you would need to do is make sure your promise producer (body) has a suitable delay in it before making the network call.

    /**
    Repeadetly evaluates a promise producer until a value satisfies the predicate.
    `promiseWhile` produces a promise with the supplied `producer` and then waits
    for it to resolve. If the resolved value satifies the predicate then the
    returned promise will fulfill. Otherwise, it will produce a new promise. The
    method continues to do this until the predicate is satisfied or an error occurs.
    - Returns: A promise that is guaranteed to fulfill with a value that satisfies
    the predicate, or reject.
    */
    
    func promiseWhile<T>(pred: (T) -> Bool, body: () -> Promise<T>, fail: (() -> Promise<Void>)? = nil) -> Promise<T> {
        return Promise { fulfill, reject in
            func loop() {
                body().then { (t) -> Void in
                    if !pred(t) { fulfill(t) }
                    else {
                        if let fail = fail {
                            fail().then { loop() }
                            .error { reject($0) }
                        }
                        else { loop() }
                    }
                }
                .error { reject($0) }
            }
            loop()
        }
    }