Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change Promise properties: isPending, isFulfilled, isRejected from In… #31

Closed
wants to merge 1 commit into from
Closed

Conversation

ghost
Copy link

@ghost ghost commented Mar 3, 2018

Change Promise properties: isPending, isFulfilled, isRejected from Internal to Public

@googlebot
Copy link

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed (or fixed any issues), please reply here (e.g. I signed it!) and we'll verify it.


What to do if you already signed the CLA

Individual signers
Corporate signers
  • Your company has a Point of Contact who decides which employees are authorized to participate. Ask your POC to be added to the group of authorized contributors. If you don't know who your Point of Contact is, direct the project maintainer to go/cla#troubleshoot.
  • The email used to register you as an authorized contributor must be the email used for the Git commit. Check your existing CLA data and verify that your email is set on your git commits.
  • The email used to register you as an authorized contributor must also be attached to your GitHub account.

@shoumikhin
Copy link
Contributor

Hi @oxview, could you provide any more info on why you believe exposing those properties is necessary?

@ghost
Copy link
Author

ghost commented Mar 6, 2018

Hi @shoumikhin, I have something like this:

var promise: Promise<Void>

func connect() -> Promise<Void> {
    self.promise = Promise<Void>.pending()
    
    // connect to host ...
    
    return self.promise
}

func socket(didConnectToHost host: String) {
    self.promise.fulfill(())
}

func socket(didDisconnectFromHost host: String) {
    if self.promise.isPending {
        self.promise.reject("some error")
        
        // we are sure that we was not connected, self.promise was not fullfiled/rejected
        // do 1 logic ...
    } else {
        // do 2 logic ...
    }
}

@ghost
Copy link
Author

ghost commented Mar 6, 2018

@shoumikhin Moving from other Promises someone throw exception if promise is already NOT in pending state and you try to fulfill or reject it, in google/promises it will be ignored, I understand that doing this now will break API, but because human factor are not excluded throwing exception on fulfill/reject if not in pending state sometime help to prevent wrong logic (helpful for beginners), but this is just a suggestion.

@shoumikhin
Copy link
Contributor

Thanks you for the details!

Are you using some kind of a networking library that provides a delegate to notify about connections? Wonder if there's any API which provides a completion handler instead, which you could then wrap with resolve?

If no, and being a delegate is the only way, how about a nullable Promise?

var promise: Promise<Void>?

func connect() -> Promise<Void> {
    if promise != nil {
        promise?.reject(MyError.abandoned)
        promise = nil
    }
    let newPromise = Promise<Void>.pending()
    promise = newPromise

    // connect to host ...
    
    return newPromise
}

func socket(didConnectToHost host: String) {
    promise?.fulfill(())
    promise = nil
}

func socket(didDisconnectFromHost host: String) {
    if promise != nil {
        promise?.reject(MyError.disconnected)
        promise = nil

        // we are sure that we was not connected, self.promise was not fullfiled/rejected
        // do 1 logic ...
    } else {
        // do 2 logic ...
    }
}

Just make sure the users of such promise won't introduce retain cycles with something like:

object.connect().then { _ in
  object.doSomethingElse() 
  // object is now captured by the block which is captured by the promise returned from connect(), which in turn is owned by the object
  // although, the retain cycle will get broken once the promise gets resolved in either delegate call and nullified
}

Anyhow, checking the state of a promise with isPending() for logical branching is potentially error-prone, because the promise can get resolved on a background thread immediately after such check. Those methods are available for testing purposes only, so you need to @testable import Promises to get them.

@ghost
Copy link
Author

ghost commented Mar 7, 2018

Thank you for you advise and I am absolutely agree with checking the state of a promise with isPending() for logical branching is potentially error-prone I will rewrite my code. We can close this

@ghost ghost closed this Mar 7, 2018
This was referenced Jul 31, 2018
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants