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

Request for a Custom Thenable Handler #432

Closed
markbjerke opened this issue Feb 26, 2015 · 9 comments
Closed

Request for a Custom Thenable Handler #432

markbjerke opened this issue Feb 26, 2015 · 9 comments

Comments

@markbjerke
Copy link

I have thenable objects in my library. When I return a thenable instance from a promise a Thenable handler is created.

I want my thenable's to resolve to themselves. This however creates a cycle ( that is not detected, it would not be hard however) which of course breaks the code.

If the getHandler() method was plugable or an override allowed me to return an instance of my thenable and have it stay resolved; I could get the design I want.

So basically I just want to do something like : entity.then(...) whereI resolve with entity and not cycle.

I would like my library users to use entity.then(...), to simplify the code which is mixed with promises A+. However it makes the most sense for entity.then(...) to resolve to itself.

I guess this needs to be evaluated in light of EcmaScript 6. I have a feeling I might not be using the concept correctly since this type of integration doesn't seem to work.

thanks in advance
mark

@unscriptable
Copy link
Member

Hey Mark.

I want my thenable's to resolve to themselves.

I went down this path, too. I think a lot of folks do. :) It never works out the way you want it to and will add complexity, rather than remove it in JavaScript.

The best way to think about promises IMHO is as proxies for future values with a built-in resolution notification.

If the getHandler() method was plugable or an override allowed me to return an instance…

I'll let Brian answer this part, but I suspect you would be better off thinking abiut promises as proxies.

-- john

@briancavalier
Copy link
Member

@markbjerke Like @unscriptable mentioned, each time I've gone down the road or seen someone go down the road of merging business objects and promises, it never seems to end well. There tend several reasons for this.

One is that if you have your hands on one of these objects, you can't necessarily tell whether it's internal state is valid or not, since it may represent a version of itself that is only valid in the future. In that case, your best bet is just to call then on it, at which point it may as well have been a pure promise in the first place.

Another is that in browsers and node now, it is extremely common for several promise implementations to be in play. For merged business-promise objects to be usable and safe, all of these implementations would need to behave the same way. That's unlikely to happen, especially now that native promises are being shipped in many environments, and there are several widely used 3rd party promise implementations. Your application could suddenly break if, through refactoring, evolution of the application over time, or simply pulling in a new 3rd party lib dependency (which happened to use Q, RSVP, or Bluebird, for example), some other kind of promise made its way into the system.

I think the best path is to keep the two concepts separate: build operations that return promises for business objects, rather than building business objects that are promises.

@markbjerke
Copy link
Author

I tried using our entities as thenables with a ( native ) promise in Chrome and it resulted in similar behavior (cycle/crash).

In the design a user has an instance that goes through a status update as opposed to having a promise for an instance. Essentially the design is clearer (we think) if users have an inspect-able object with an identity as a return value. There are meta properties on the entity that describe it in terms of noun / status, etc.. using an '@' sign to differentiate from 'normal' entity properties. In particular it's nice from consoles / node to know what you are getting immediately.

There is an '@value' meta property which is a promise. There is a sugar method over the entities value promise. The code looks like; entity.continue(resolve, reject, progress). I wanted to change this method to entity.then(...) ; I agree that our business objects are not Promises.

Thanks for the help in this case the goal of simplifying by changing the method name went too far.

thanks
mark

@rkaw92
Copy link
Contributor

rkaw92 commented Mar 2, 2015

Hello from a dev creating an Event-Sourcing DDD framework. Your final approach is what I've chosen as well, should the user want to operate on immutable objects as their primary means of changing entity state.

In my project, a Repository component allows you to load an Aggregate Root (representing an Entity) and execute a function on it. Whatever that function returns as its fulfillment value, the repository assumes to be the final state of the AR. If the promise does not yield anything, it is assumed that the user did not want to use immutability after all and the original object is considered the new state (because it is supposed to have been changed by the function passed to the repository call). This way, both Scala-like immutability and classical JS pass-by-reference semantics can be reconciled.

Just my two eurocents so that you can get a bigger picture.

@sompylasar
Copy link

Hello devs! I've recently hit a similar problem: I needed entities to be thenables that can resolve to themselves. I've developed a solution using when. Please have a look:
https://gist.github.com/sompylasar/3515c93c1e579c5cc352

@markbjerke
Copy link
Author

Hello Devs!, I'm now wondering whether I should have inherited from Promise in the first place. Are people doing that ? Is that a crazy idea ? Oh, by the way thanks for the feedback, I'm currently trying to clean up our business objects. It's not horrible saying entity.continue(...), so we're not stuck however since the code is using promises dev's can get confused at times.

@briancavalier
Copy link
Member

@markbjerke My personal feeling is that it's ok to inherit from Promise in order to create a specialized type of promise, e.g. a cancelable promise, or something like that. I'm not a fan of inheriting from Promise to create business objects or anything that's distinctly not a promise to start with.

In my mind, this makes sense: CancelablePromise is a Promise
But this doesn't: Employee is a Promise

@briancavalier
Copy link
Member

Ping @markbjerke. Any thoughts on where we stand on this one? Have you found a solution that works for you?

@briancavalier
Copy link
Member

Closing. Please feel free to reopen if you want to continue to discuss.

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

No branches or pull requests

5 participants