google / promises

Promises is a modern framework that provides a synchronization construct for Swift and Objective-C.
Apache License 2.0
3.79k stars 292 forks source link

Can't reject retry promise #175

Closed piroznoe closed 2 years ago

piroznoe commented 2 years ago

Why I can't reject promise at some point of time?

Version: 1.2.8

 let promise = retry(attempts: 100, delay: 1) {
    Promise(0).validate { _ in false }
  }

  DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
    promise.reject(.canceled)
  }
chuckhays commented 2 years ago

To cancel a retry block you would need to use the condition parameter:

  var shouldContinue = true

  let promise = retry(attempts: 100, delay: 1, condition: { attempsRemaining, error in
    return shouldContinue
  }) {
    Promise(0).validate { _ in false }
  }

  DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
    shouldContinue = false
  }
piroznoe commented 2 years ago

I have already used this solution But it is confusing, why I can’t reject promise with reject method

chuckhays commented 2 years ago

You can reject the promise the way you suggested, and it will call the .catch block on the promise, but it will not stop the retry attempts from executing.

piroznoe commented 2 years ago
let promise = retry(attempts: 100, delay: 1) {
   Promise(0).validate { _ in false }
}.catch { error in
  // error block 1
}

promise.catch { error in
  // error block 2
}

promise.catch { error in
  // error block 3
}

Only block 2 and 3 will be called after calling promise.reject(.canceled). Is it expected behaviour?

chuckhays commented 2 years ago

If you reject promise in that example you are rejecting the promise returned by the .catch function, which isn't the same promise object from the retry block.

A simplified example without retry:

    let p1 = Promise<String>.pending()
    p1.then { s in
      print("Then block: \(s)")
    }
    let p2 = p1.catch { e in
      print("Error block 1: \(e)")
    }
    p2.catch { e in
      print("Error block 2: \(e)")
    }
    p2.catch { e in
      print("Error block 3: \(e)")
    }
    p2.reject(NSError(domain: "test", code: -1))

Rejecting p2 will print only blocks 2 and 3, but rejecting p1 would print all 3 catch blocks.