Writing bindings that depend on Promises


#1

Hi all! For the past several months, I’ve been working on an app with my own bindings for apollo-client and react-apollo that differ from the more official ones in the way they treat GraphQL typings (which is a topic for another post…). I’d like to move mine into a separate repo and OSS them in case anyone else wants to give them a try, but I’m hung up on the best way to handle Promises.

Pretty early on in writing mine, I decided to utilize repromise to to represent the result of any async actions. To me, writing code with repromise feels like a massive improvement over Js.Promise, and is more type-safe as well. While I’d love to keep using repromise in my OSS bindings, I’m not naive enough to think that some folks wouldn’t appreciate being forced into using that lib ;).

It’s been a while since I’ve looked into what the Reason community is doing in the async space. I know a number of folks have been unhappy with the Js.Promise paradigm, so I was wondering if anyone knows if a better approach to handling async that doesn’t depend on a 3rd-party library (or, maybe depends on a more accepted-by-the-community 3d party library)?

I suppose the other option would be to write my bindings with Js.Promise and then also provide an adapter for use with repromise?

Anyway, I’d love to hear people’s thoughts on this! Thanks!


#2

From what I have seen there seem to be plenty of options in the Promise space:

Including what you have mentioned already:

This topic is ripe for debate on all sides. I would say use what you think is best and move the community forward. Js.Promise has many issues all of which has been talked about at length:

Let’s learn from the mistakes of the past and encourage people to use a more sound async primitive.


#3

One thing I like about RationalJS/future is that it reuses Result, which is arguably better for composability than two separate continuations.


#4

I have to agree with this. result is pretty much the standard in OCaml as well as having an polyfill in Bucklescript.

repromise has this weird rejectable type that needs to be converted back to result type.

I also dislike the push for “more convenient” for beginner and JS developers. I’m a JS developers by heart and I was pretty confused at first when seeing andThen. I mean why? When flatMap is pretty standard in Javascript.

</rant>


#5

On the topic of convenience (sorry, couldn’t pass it :smiley:), I think in the long run it would be more convenient for both beginners and experienced devs alike if Reason ecosystem had more consistency, even if it meant a steeper learning curve. E.g., in the infamous discussion on Promises and map/flatMap @arecvlohe mentioned above, Reason should rather take the side of category theory than that of JS legacy.

Of course, it’s a long way before the ecosystem matures, especially since OCaml is a bigger language than, say, Elm, and BuckleScript offers way more integration with JS-land. But in the end, I think Reason would greatly benefit from making DX as great as possible in ML-land, pushing all kinds of JavaScript legacy as near to the edges as practically possible.


#6

Thanks for the replies!

I’d not seen Future before, and I agree that its use of Belt.Result is a very nice convention over the way repromise handles it. And it seems to be under more active development, which is also nice. That said, it’s based solely off of GH’s “used by” tab, it still doesn’t seem to have that much adoption… which it seems could be said of all the others, too.

I’m all for trying to move the community towards a single implementation if at all possible, with the understanding that we’re maybe still a ways away from actually landing on anything. Is there a broader discussion about this happening anywhere else, besides the discussion around Js.Promise's drawbacks? I still chafe a little at the idea of releasing a binding that locks you into another library for your async code, but on the other hand if enough people agreed to do that maybe it’d actually spur adoption? Maybe that’s even the way forward - if we agree to focus on one async approach and get the owners of the more popular async-related binding libraries to release versions that work with that approach? Outside of something actually getting included in BS, that seems like the best possible way to push people to use something other than Js.Promise.


#7

Well, I think you can always vote for a project by a) using it and b) contributing to it. In my personal case, Future seems nice and, for a solution that would probably be used a lot, if at all, easy enough to support (like maybe contribute to, or even fork and maintain) in case it gets abandoned.

And if I decide to drop it, at least I won’t have to refactor away all those results, which would probably be allowed closer to the domain core than the async IO.


#8

One thing I like about RationalJS/future is that it reuses Result, which is arguably better for composability than two separate continuations.

Does future address the type soundness issue as enumerated and fixed in `repromise’ in https://aantron.github.io/repromise/docs/DesignFAQ#why-are-js-promises-not-type-safe?


#9

Definitely yes!

And at a matter of fact, if something is implemented purely in ReasonML (which future is), and it doesn’t use type casting, it will have type soundness