I'm mostly using programming languages like Scala and JavaScript. I'm trying to understand the similarities and differences in how async reactive programming is used in both languages. Can you help me?
I'm not taking any particular Js Promise
framework because it seems many implement the similar specifications (like Promise/A). I've only used Q so far.
It seems that in Javascript we call a Deferred
the object we resolve to complete a Promise
.
In Scala, it seems the Promise
is the object you resolve to get a Future
monad.
Can someone tell me if this is right? Is there any good reason for a different usage of the term Promise
between Js and Scala?
Also, in Scala we usually chain Future
monads with further computations using operators like map
and flatMap
(also called bind
in Haskell). What is the equivalent of these in Js?
I may be wrong but it appears to me that in Js the then
on a Promise
kind of handle both map
and flatMap
operators right? If so, is it possible to obtain a promise of promise of result
in Js? Like we can get a Future[Future[Result]]
in Scala (which can be flattened to a Future[Result]
anyway).
Is Js Promise
a monad? It kind of seems so even if the method names do not really match those we find on monad literature.
While extremely similar. With JavaScript Promises that comply to the Promises/A+ spec .then
is not really a monadic bind and does .map
and .flatMap
both. Inside a .then
handler when you return a promise it will recursively unwrap it.
Promise.delay(1000).then(function() {
return Promise.delay(1000).then(function () {
return Promise.delay(2000);
}).then(function () {
return Promise.delay(5000)
});
}).then(function () {
alert("This is only shown after 8 seconds and not one");
});
You are correct that the standard JS promise libraries and the A+ spec does not feature monadic promises. They have been discussed, and implementations like fantasy-promises exist. They follow a differnet spec and have little adoption. Also see this. There has been ongoing discussion about it in the language design discussion forum - esdiscuss and a monadic .chain
method that does not flatmap and allows for monadic promises is considered but unlikely to make it.
This is for pragmatic reasons. The current way promises are implemented is immensely useful. Rare are the cases you actually want a Future[Future
and normally you want continuations to just work in the language. Promises 'borrow' from monads and are 'monadic' in a sense themselves. .then
is very close to bind and in my head I use them interchangeably :)
It is impossible to have a Promise[Promise[Value]]
like a Future[Future[Value]]
in Scala with most promise libraries. You'd have to wrap it in an object and have Promise[Container[Promise[Value]]]
.
Promise.delay(1000).then(function () {
return Promise.delay(1000).then(function () {
return {
wrap: Promise.delay(2000).then(function () {
return Promise.delay(5000);
})
};
});
}).then(function () {
alert("This logs after 1 second");
// I've also not seen a really solid use case
// except TypeScript type inference which is meh
});
There are also a number of other smaller differences between the two, but generally you are correct in your assertions.