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 bindin 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.
Yes, and no.
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");
});
(fiddle)
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
});
(fiddle)
There are also a number of other smaller differences between the two, but generally you are correct in your assertions.
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?
In Scala, Promise and Future have separated functionality, Future is a asynchronous computation container, which return you some value in the future, and Promise is the writing part for async-computation, which you can do something as follow
val promise = Promise[String]
val future1 = promise.future
val future2 = future1.map { case s => println(s); s }
future2.onSuccess { case s => println(s + " 2nd time") }
promise.success("promise completed")
Once you execute the last statement, the output will be
promise completed
promise completed 2nd time
In Scala,you read value from Future using onComplete, or you chain it using map, and you write to a Future using it's Promise counterpart
In JS Promise A+ specs, they are bundled together, Promise.then is used for both chaining and retrieving value for side-effect (eg. console.log), to write you will use resolve like code snippet below
var promise = new Promise(function(resolve, reject){
Thread.sleep(10000);
resolve("promise completed");
}
I'm trying to understand the similarities and differences in how async reactive programming is used in both languages.
This document here doesn't compare Javascript promises with Scala, but instead Javascript promises with C++ C# and Python: https://github.com/KjellSchubert/promise-future-task. I know thats not exactly what you had asked for, but this might give you some interesting pointers nonetheless.
In contrast to Scala,
the JS Promise is not a monad,
due to the implicit "thenable" unwrapping breaking monadic law.
You can, however, implement a callback-based monadic semantics and functionality, serving the same purpose.
See e.g. the cpsfy library.
In addition, there is a structural difference due to .then accepting 2 functions, while .chain accepts only one. However, a chain accepting 2 or even any number of argument functions can be implemented, like e.g. with
CPS wrapper from cpsfy:
//function returning CPS function with 2 callbacks
const readFileCps = file => (onRes, onErr) =>
require('fs').readFile(file, (err, content) => {
err ? onErr(err) : onRes(content)
})
// CPS wraps a CPS function to provide the API methods
const getLines = CPS(readFileCps('name.txt'))
// map applies function to the file content
.map(file => file.trim())
.filter(file => file.length > 0)
// chain applies function that returns CPS function
.chain(file => readFileCps(file))
.map(text => text.split('\n'))
// => CPS function with 2 callbacks
// To use, simply pass callbacks in the same order
getLines(
lines => console.log(lines), // onRes callback
err => console.error(err) // onErr callback
)
Related
The inconvenience I have is that there is no way, to my knowledge, using built-in Promise, to resolve a Promise within a synchronous block.
Specifically, the following code
var o = {};
function set(index, value) {
console.log(`setting ${index} to ${o.index = value}`);
}
Promise.resolve().then(()=>set('a', 1)).then(()=>set('b',2))
Promise.resolve().then(()=>set('c', 1)).then(()=>set('d',2))
console.log(`a is ${o.a}`);
Outputs :
a is undefined
setting a to 1
setting c to 1
setting b to 2
setting d to 2
Are there Promise like lib whose Promise would yield the following outputs:
setting a to 1
setting b to 2
setting c to 1
setting d to 2
a is 1
Obviously, no need to resort to Promises in the example above, but in my use case, setting 'a' leads to a pretreatment which only needs to be done once, whereas 'b' can be set multiple times, and is used within the same synchronous block it is set (no freedom on that).
I've looked up bluebird, and I have no clue how their promises work internally, but they seem to embrace using only promise chains.
Q Promise might be what I'm looking for, I'm not sure.
More generally, it feels daunting scouring the docs of the many Promise librairies out there querying some niche, depreciated need with likely the wrong keywords and concepts in mind.
This is definitely a case of ProblemXY where X could be solved in a variety of ways without Promises, for example by synchronous initializers, but I feel problem Y is interesting in and of itself (and likely a duplicate), so I'm still asking.
I'll get around giving problem X its own question, but long story short, I'd love to use, sometimes within a single js synchronous execution block, the expressive power of promises to pull values instead of pushing them and to flatten callbacks and try-catch pyramids.
Edit:
To clarify what I'm curious about, the way I would build the Promiselike with the desired properties is as follow :
let f = myPasync(function*(){ //equivalent to async function declaration
v = yield myPAwait(myPromiseInstance); //equivalent of v = await myPromiseInstance;
})
let pa = new myP( *(resolve, reject)=>{} ) //equivalent to new Promise((resolve, reject)=>{}) ; for simplicity, resolve and reject can be naked properties of pa
pa.myPthen((*()=>{})()) //equivalent to pa.then((v)=>{})
And then, instead of dynamically iterating over a task queue every tick, pushing thens and awaits of newly resolved promised to that queue in a FIFO manner,
I would push to the task queue in a LIFO manner and iterate over it upon any myP related function call.
So for example, when a promise is resolved, every routine awaiting it will resume before anything else, and in particular before the rest of the routine resolving the promise.
Other example when a routine awaits a promise, if that promise is already resolved, the routine is immediately resumed instead of letting other execute.
As I know, Promises are used to represent success/failure of an asynchronous operation. When I am looking into one of my project, all the functions are wrapping the final result in 'Promise.resolve'. I am not understanding, what is the use of wrapping all the function results in 'Promise.resolve'. Is there any use case here?
For example, all the functions are following below template.
process = (data) => {
//Perform some operations.
return Promise.resolve(result);
}
The only reason to use Promise.resolve is converting a value that might be a promise to a promise.
Promise.resolve(value) is a convenience method that does new Promise(resolve => resolve(value). If the value is a promise it will be returned, if it is a promise from a userland promise library it will be converted to a native promise. If it is a plain value it will be converted for a promise fulfilled with that value.
Promise.resolve(5); // returns a promise fulfilled with the number 5.
This is useful in several cases, for example:
- If a function might return a promise, it should always return a promise - so for example if you have a cached value it might need to be Promise.resolved.
- If there are multiple implementations of functionality and some are synchronous - it creates a uniform interface.
Note that in practice with async functions this is not needed so much anymore since an async function always returns a promise - even if you return a plain value (in fact, whatever you return from an async function is Promise.resolved implicitly).
Also note that in particular you shouldn't make functions return promises if all they do is synchronous computation since a function returning a promise implies I/O in JavaScript.
In this answer, a promise chain is built recursively.
Simplified slightly, we have :
function foo() {
function doo() {
// always return a promise
if (/* more to do */) {
return doSomethingAsync().then(doo);
} else {
return Promise.resolve();
}
}
return doo(); // returns a promise
}
Presumably this would give rise to a call stack and a promise chain - ie "deep" and "wide".
I would anticipate a memory spike larger than either performing a recursion or building a promise chain alone.
Is this so?
Has anyone considered the memory issues of building a chain in this way?
Would memory consumption differ between promise libs?
a call stack and a promise chain - ie "deep" and "wide".
Actually, no. There is no promise chain here as we know it from doSomeThingAsynchronous.then(doSomethingAsynchronous).then(doSomethingAsynchronous).… (which is what Promise.each or Promise.reduce might do to sequentially execute handlers if it was written this way).
What we are facing here is a resolve chain1 - what happens in the end, when the base case of the recursion is met, is something like Promise.resolve(Promise.resolve(Promise.resolve(…))). This is only "deep", not "wide", if you want to call it that.
I would anticipate a memory spike larger than either performing a recursion or building a promise chain alone.
Not a spike actually. You'd slowly, over time, build a bulk of promises that are resolved with the innermost one, all representing the same result. When, at the end of your task, the condition is fulfilled and the innermost promise resolved with an actual value, all of these promises should be resolved with the same value. That would end up with O(n) cost for walking up the resolve chain (if implemented naively, this might even be done recursively and cause a stack overflow). After that, all the promises except for the outermost can become garbage collected.
In contrast, a promise chain that is built by something like
[…].reduce(function(prev, val) {
// successive execution of fn for all vals in array
return prev.then(() => fn(val));
}, Promise.resolve())
would show a spike, allocating n promise objects at the same time, and then slowly resolve them one by one, garbage-collecting the previous ones until only the settled end promise is alive.
memory
^ resolve promise "then" (tail)
| chain chain recursion
| /| |\
| / | | \
| / | | \
| ___/ |___ ___| \___ ___________
|
+----------------------------------------------> time
Is this so?
Not necessarily. As said above, all the promises in that bulk are in the end resolved with the same value2, so all we would need is to store the outermost and the innermost promise at one time. All intermediate promises may become garbage-collected as soon as possible, and we want to run this recursion in constant space and time.
In fact, this recursive construct is totally necessary for asynchronous loops with a dynamic condition (no fixed number of steps), you cannot really avoid it. In Haskell, where this is used all the time for the IO monad, an optimisation for it is implemented just because of this case. It is very similar to tail call recursion, which is routinely eliminated by compilers.
Has anyone considered the memory issues of building a chain in this way?
Yes. This was discussed at promises/aplus for example, though with no outcome yet.
Many promise libraries do support iteration helpers to avoid the spike of promise then chains, like Bluebird's each and map methods.
My own promise library3,4 does feature resolve chains without introducing memory or runtime overhead. When one promise adopts another (even if still pending), they become indistinguishable, and intermediate promises are no longer referenced anywhere.
Would memory consumption differ between promise libs?
Yes. While this case can be optimised, it seldom is. Specifically, the ES6 spec does require Promises to inspect the value at every resolve call, so collapsing the chain is not possible. The promises in the chain might even be resolved with different values (by constructing an example object that abuses getters, not in real life). The issue was raised on esdiscuss but remains unresolved.
So if you use a leaking implementation, but need asynchronous recursion, then you better switch back to callbacks and use the deferred antipattern to propagate the innermost promise result to a single result promise.
[1]: no official terminology
[2]: well, they are resolved with each other. But we want to resolve them with the same value, we expect that
[3]: undocumented playground, passes aplus. Read the code at your own peril: https://github.com/bergus/F-Promise
[4]: also implemented for Creed in this pull request
Disclaimer: premature optimization is bad, the real way to find out about performance differences is to benchmark your code, and you shouldn't worry about this (I've only had to once and I've used promises for at least 100 projects).
Is this so?
Yes, the promises would have to "remember" what they're following, if you do this for 10000 promises you'd have a 10000 long promise chain, if you don't then you won't (for example, with recursion) - this is true for any queueing flow control.
If you have to keep track of 10000 extra things (the operations) then you need to keep memory for it and that takes time, if that number is a million it might not be viable. This varies among libraries.
Has anyone considered the memory issues of building a chain in this way?
Of course, this is a big issue, and a use case for using something like Promise.each in libraries like bluebird over thenable chaining.
I've personally had in my code to avoid this style for a quick app that traverses all the files in a VM once - but in the vast majority of cases it's a non issue.
Would memory consumption differ between promise libs?
Yes, greatly. For example bluebird 3.0 will not allocate an extra queue if it detects a promise operation is already asynchronous (for example if it starts with a Promise.delay) and will just execute things synchronously (because the async guarantees are already preserved).
This means that what I claimed in my answer to the first question isn't always true (but is true in the regular use case) :) Native promises will never be able to do this unless internal support is provided.
Then again - it's no surprise since promise libraries differ by orders of magnitude from one another.
I just came out a hack that may help solving the problem: don't do recursion in the last then, rather, do it in the last catch, since catch is out of the resolve chain. Using your example, it would be like this:
function foo() {
function doo() {
// always return a promise
if (/* more to do */) {
return doSomethingAsync().then(function(){
throw "next";
}).catch(function(err) {
if (err == "next") doo();
})
} else {
return Promise.resolve();
}
}
return doo(); // returns a promise
}
To complement the awesome existing answers I'd like to illustrate the expression, which is the result of such an asynchronous recursion. For the sake of simplicity I use a simple function that computes the power of a given base and exponent. The recursive and base case are equivalent to those of the OP's example:
const powerp = (base, exp) => exp === 0
? Promise.resolve(1)
: new Promise(res => setTimeout(res, 0, exp)).then(
exp => power(base, exp - 1).then(x => x * base)
);
powerp(2, 8); // Promise {...[[PromiseValue]]: 256}
With the help of some substitution steps the recursive portion can be replaced. Please note that this expression can be evaluated in your browser:
// apply powerp with 2 and 8 and substitute the recursive case:
8 === 0 ? Promise.resolve(1) : new Promise(res => setTimeout(res, 0, 8)).then(
res => 7 === 0 ? Promise.resolve(1) : new Promise(res => setTimeout(res, 0, 7)).then(
res => 6 === 0 ? Promise.resolve(1) : new Promise(res => setTimeout(res, 0, 6)).then(
res => 5 === 0 ? Promise.resolve(1) : new Promise(res => setTimeout(res, 0, 5)).then(
res => 4 === 0 ? Promise.resolve(1) : new Promise(res => setTimeout(res, 0, 4)).then(
res => 3 === 0 ? Promise.resolve(1) : new Promise(res => setTimeout(res, 0, 3)).then(
res => 2 === 0 ? Promise.resolve(1) : new Promise(res => setTimeout(res, 0, 2)).then(
res => 1 === 0 ? Promise.resolve(1) : new Promise(res => setTimeout(res, 0, 1)).then(
res => Promise.resolve(1)
).then(x => x * 2)
).then(x => x * 2)
).then(x => x * 2)
).then(x => x * 2)
).then(x => x * 2)
).then(x => x * 2)
).then(x => x * 2)
).then(x => x * 2); // Promise {...[[PromiseValue]]: 256}
Interpretation:
With new Promise(res => setTimeout(res, 0, 8)) the executor is invoked immediately and executes a non-bllocking computation (mimicked with setTimeout). Then an unsettled Promise is returned. This is equivalent with doSomethingAsync() of the OP's example.
A resolve callback is associated with this Promise via .then(.... Note: The body of this callback was substituted with the body of powerp.
Point 2) is repeated and a nested then handler structure is build up until the base case of the recursion is reached. The base case returns a Promise resolved with 1.
The nested then handler structure is "unwound" by calling the associated callback correspondingly.
Why is the generated structure nested and not chained? Because the recursive case within the then handlers prevents them from returning a value until the base case is reached.
How can this work without a stack? The associated callbacks form a "chain", which bridges the successive microtasks of the main event loop.
This promise pattern will generate a recursive chain. So, each resolve() will create a new stack frame (with its own data), utilizing some memory. This means that large number of chained functions using this promise pattern can produce stack overflow errors.
To illustrate this, I'll use a tiny promise library called Sequence, which I've written. It relies on recursion to achieve sequential execution for chained functions:
var funcA = function() {
setTimeout(function() {console.log("funcA")}, 2000);
};
var funcB = function() {
setTimeout(function() {console.log("funcB")}, 1000);
};
sequence().chain(funcA).chain(funcB).execute();
Sequence works great for small/medium sized chains, in the range of 0-500 functions. However, at about 600 chains Sequence starts degradating and generating often stack overflow errors.
The bottom line is: currently, recursion-based promise libraries are more suitable for smaller/medium sized function chains, while reduce-based promise implementations are ok for all cases, including larger chains.
This of course doesn't mean that recursion-based promises are bad. We just need to use them with their limitations in mind. Also, it's rare that you'll need to chain that many calls (>=500) via promises. I typically find myself using them for async configurations which utilize heavily ajax. But even if the most complex cases I haven't seen a situation with more than 15 chains.
On a side note...
These statistics were retrieved from tests performed with another of my libraries - provisnr - which captures the achieved number of function calls within a given interval of time.
I'm writing a nodejs thing, and trying the Pacta promise library for fun. Pacta's interface is "algebraic," but I don't have any experience with that paradigm.
I'd like to know what is the "Pacta way" to accomplish the same thing as
$.when.apply(undefined, arrayOfThings)
.then(function onceAllThingsAreResolved(thing1Val, thing2Val, ...) {
// code that executes once all things have been coerced to settled promises
// and which receives ordered resolution values, either as
// separate args or as a single array arg
}
That is, given an array, an iterator function that returns a promise, and a callback function, I'd like to map the iterator onto the array and provide an array of the resolution values (or rejection reasons) to the callback once all the promises have been settled.
If there isn't an idiomatically algebraic way to express this, I'd be just as interested to know that.
EDIT: updated use of $.when to properly accommodate an array, per #Bergi.
Pacta's interface is "algebraic," but I don't have any experience with that paradigm.
ADTs are type theory constructs that represent nested data types, like a Promise for Integer. They are heavily used in functional programming, a flavour where you always know the types of your expressions and values. There are no intransparent, implicit type coercions, but only explicit ones.
This is completely contrary to jQuery's approach, where $.when() and .then() do completely different things based on the types (and number) of its arguments. Therefore, translating your code is a bit complicated. Admittedly, Pacta doesn't have the most useful implementation, so we have to use some own helper functions to do this.
Assume you have an array of (multiple) promises, and your then callback takes the arguments and returns a non-promise value:
arrayOfPromises.reduce(function(arr, val) {
return arr.append(val);
}, Promise.of([])).spread(function (…args) {
// code that executes once all promises have been fulfilled
// and which receives the resolution values as separate args
});
If your callback does not take multiple arguments, use map instead of spread:
arrayOfPromises.reduce(function(arrp, valp) {
return arrp.append(valp);
}, Promise.of([])).map(function (arr) {
// code that executes once all promises have been fulfilled
// and which receives the resolution values as an array
});
If your callback does return a promise, use chain instead of map:
arrayOfPromises.reduce(function(arr, val) {
return arr.append(val);
}, Promise.of([])).chain(function (arr) {
// code that executes once all promises have been fulfilled
// and which receives the resolution values as an array
});
If you don't know what it returns, use then instead of chain. If you don't know what it returns and want to get multiple arguments, use .spread(…).then(identity).
If your array contains promises mixed with plain values, use the following:
arrayOfThings.reduce(function(arrp, val) {
var p = new Promise();
Promise.resolve(p, val);
return arrp.append(p);
}, Promise.of([])).…
If your array contains only a single or no (non-thenable) value, use
Promise.of(arrayOfThings[0]).…
If your array contains anything else, even $.when would not do what you expect.
Of course, promises that resolve with multiple values are not supported at all - use arrays instead. Also, your callback will only be called when all promises are fulfilled, not when they're settled, just as jQuery does this.
Code example (mutability)
.factory('objSingleton', function ($q) {
var o = {a: 1}
setTimeout(function () {
o.a = 2
}, 1000)
return $q.when(o)
})
An alternative would be (immutability)
.factory('objFactory', function ($q) {
var promise = $q.when({a: 1})
setTimeout(function () {
promise = $q.when({a: 2})
}, 1000)
return function () {
return promise
}
})
Question
I'd like to hear 'for's and 'against's to help me decide between embracing or refraining from treating the promises (in the APIs that create+return them) deeply immutable.
Note: Code example uses AngularJS style dependency injector, but the question and the answer is applicable to any and all JS environments that uses promises.
Promises should not play any role in making this decision.
A promise, after all is just an abstraction over a calculation that might take time. The result of a promise, is an abstraction of a normal result.
Generally, it is good practice to have immutable values, as mutable state is really bad to have anyway. Mutable state makes testing harder. In your case, mutable global state is even worse. One of the finest articles on why is written by Angular's author Misko Havery and is called Singletons Are Pathological Liars.
So, the answer is - do what you would have done in synchronous code. Would you return a copy, or a reference in your synchronous code. This is a subjective question which I can't really answer, but all facts point to "have as little state as possible in your code".
I highly disagree with your note. The framework plays a major role in this decision. In angular, if you attach the resolved value to one or several scopes and then mutate the resolved value then angular will update all relevant views for you automagically. I consider this to be a major feature of angular and so I do mutate my resolved promise values.
If you return a new promise you need to $watch the value yourself and take care of any updates to the view. Because of this, I would not prefer to use immutable values.
In other frameworks it might not work the same way and the question could have another answer.
Promise result values should definitely be considered immutable.
Promises do promote a functional programming style, and resolving them will settle their value forever. Their contract is that they will invoke all callbacks with the exactly same value, regardless of when this happens. You should not consider this only to be object identity, but also object "state".
Not mutating result values will lead to cleaner and less error-prone code. There are even promise libraries that enforce this by Object.freezeing the resolution value.
The only downside of such an approach is that the necessary cloning of the objects will be much slower. It is however acceptable to mutate the objects if you can be absolutely sure that nobody else but you consumes these values.
In my personal view, angular does take this far too liberally, but automatic propagation of such mutations is their design.