What is Folktale's Future for? - javascript

Background
I am reading every inch of the docs and trying to learn about Folktale as much as I can.
Recently, I decide to try Future.
Do we need a Future?
Now while I understand the difference between Task and Promise and between Task and Future ( support for cancellation ) it is not clear to me the difference between Future and Promise.
Why would I ever want to use a Future instead of a Promise ? What benefits would I have?
Well, you can say: "This way you actually have a monad, instead of a sorry excuse for a monad".
And that is a fine argument on it's own but... having in mind I always need to convert from Promise to something else ( to future ) and that the Future's API is pretty much the same, it is not clear to me, as someone new, why I should care about Future at all.
Code sample
Lets assume I have this function, where request is a function that makes a request and returns some results.
extractRequestInfo is a function that extracts data from the response object.
If something fails, I catch the error and return an object with all the data, the badId and the error.
const requestFruit = request => data =>
request( data )
.then( extractRequestInfo )
.catch( error => ( { badId: prop( [ "Id" ], data ), error } ) );
Given that this is an HTTP request, I know I don't need a Task because there is no cancellation I can do here. So my options are Promise and Future.
Questions
How would I use Future in this sample?
Since this is something that can fail, should I use Result as well?

Quoting the response from the creator Quil:
Future solves the same problem Promise does, so there isn't much of a
conceptual difference between the two. The difference is more in how
they solve the problem.
Promises can either settle successfully or fail. In any transformation
you apply to a promise's value, errors thrown synchronously will be
implicitly caught and reject the promise as well. This is interesting
in async/await because you can handle these errors (synchronous and
asynchronous) in a similar way--you don't need to lift every
synchronous operation into a promise, because the runtime will do that
for you.
The downside of this is that it's very easy to catch errors that you
didn't intend to, and have your system run in an inconsistent state. I
don't think you can do much with static analysis here either.
Futures don't have that problem because nothing is lifted into a
future implicitly. If you want synchronous operations to use the
Future pipeline for handling errors, you have to put them there
explicitly. This gives you more control over error handling, and
uncaught errors will still crash the process as expected (avoiding
having your program run into inconsistent memory states for cases you
didn't predict), but it takes more effort to write programs this way.
Other than that, if you consider Tasks, Futures model the eventual
value of a Task with a success case, a failure case, and a
cancellation case. Promises only have a success case and a failure
case, so cancellation is modelled as a special failure value. This
changes the idioms for handling cancellations a bit. It's possible for
code using promises to handle failures without being aware of this
special cancellation value, which may be a problem since this value
may easily be lost during these transformations.
In codebases that mix promises and tasks, these problems are more
complicated because the implicit-lifting of errors that promises do is
not very compatible with the explicit-lifiting of errors that
tasks/futures expect (this can lead to problems like this one: #163).
Finding these bugs becomes a lot harder than if you had only promises
or only tasks/futures. Not sure what's the best way to handle these
cases yet.
For the original discussion:
https://github.com/origamitower/folktale/issues/200

Related

Can a promise be safely 'swallowed'?

I'm given a promise and am returning it at the end of my function for other code to do more actions after me. A kind of middleware, if you will.
return apiCallPromise;
Lets say for some reason I wish to stop those actions from happening and "swallow" a particular promise. For example by doing the following:
if (promiseShouldBeStopped) return new Promise((resolve) => {})
return apiCallPromise;
This correctly returns a promise, however it never resolves. And so the 'promise chain' has been stopped dead in its tracks.
This seems like an anti-pattern to me as it the promise is left pending forever. Are there any bad effects of this that I should be aware of, or is this a fine technique for "filtering" promises?
Attempt to answer my own question
Does this cause memory issues?
Future code doesn't know that this promise has been filtered out, and so fails to do any "catch" or "finally" cleanup code.
In my case this is not relevant, and I want this code to take care of those errors so that the future code doesn't have to deal with them. (this means I can guarantee that onFulfilled gives the api response, and onRejected only gives an error that is actually unexpected)

Which types of Javascript (Angular2) errors stop the page from finishing rendering

I'm new to Angular2 and have been charged with developing "robust error handling". So far I've followed the simplistic examples (console.logging) for adding custom error handling. But sometimes, if the page completely stops loading due to the error, we will want to redirect the user.
However sometimes, as below, although there are errors, the page otherwise loads completely. Are there are only certain types of errors that stop the page from completely loading? One of the following 6 types perhaps?
Any error can stop your page from rendering, depending on where it occurs in your process. Any error can fail to be caught if it is in a callback or other asynchronous action.
Be careful with terms like "robust error handling" - I've seen huge commercial projects that claim just that, but actually just silently truck over loads of issues, kind of like on error resume next.
I find the golden rules are:
If your app can continue through an exception (such as getting corrupt JSON data from a non-essential service) then that specific case should always be explicitly handled.
Otherwise a unexpected exception should always break something visible.
That second rule is counter intuitive, but it really is best practice. Users will complain about errors that they see, and visible exceptions and crashes will upset them and reduce their confidence in your application.
However, exceptions that they don't see still happened, and because you've silently trucked through them whatever caused them is still there. Silent exceptions cause data to be lost or corrupted. They cause the kind of bugs that you only find out about after 6 months in production. They cause the kind of bugs you can get sued over.
Users will forgive you for obvious errors that you fix quick, they will leave and never come back if you lose data and don't immediately know about it.
Ok, so that all said, the errors you seem to be highlighting are asynchronous, and related to a problem sometimes described as callback hell.
In your screenshot the error is from an HTTP GET request - this will typically be a method where you make an AJAX request, have a callback to fire when it succeeds, but don't have a callback to handle the exception.
Angular2 uses promises, which is the next error line of your screenshot. Promises wrap those callbacks and allow you to chain them - they really help with callback hell, but they're not a magic bullet: you have to make sure that every .then() has an error handler or a following .catch().
However, there is an even better way: with Angular2 you can use TypeScript, and that means you can use async and await. These are syntactic sugar for promises, but they also work with try-catch to make error handling of asynchronous exceptions much easier.
I've blogged about that in a lot more detail than I can fit here.
TL;DR: in Angular2 use async/await (with TS transpilation if you need it) to make sure that your Promise and callback exceptions make it back up, and then handle what you expect/can work around and visibly crash for what you can't.

return deferred or deferred.promise() [duplicate]

What are the differences between Deferreds, Promises and Futures?
Is there a generally approved theory behind all these three?
These answers, including the selected answer, are good for introducing promises
conceptually, but lacking in specifics of what exactly the differences are in
the terminology that arises when using libraries implementing them (and there
are important differences).
Since it is still an evolving spec, the answer currently comes from attempting to survey both references (like wikipedia) and implementations (like jQuery):
Deferred: Never described in popular references,
1
2
3
4
but commonly used by implementations as the arbiter of promise resolution (implementing resolve and reject).
5
6
7
Sometimes deferreds are also promises (implementing then),
5
6
other times it's seen as more pure to have the Deferred only
capable of resolution, and forcing the user to access the promise for
using then.
7
Promise: The most all-encompasing word for the strategy under discussion.
A proxy object storing the result of a target function whose
synchronicity we would like to abstract, plus exposing a then function
accepting another target function and returning a new promise.
2
Example from CommonJS:
> asyncComputeTheAnswerToEverything()
.then(addTwo)
.then(printResult);
44
Always described in popular references, although never specified as to
whose responsibility resolution falls to.
1
2
3
4
Always present in popular implementations, and never given
resolution abilites.
5
6
7
Future: a seemingly deprecated term found in some popular references
1
and at least one popular implementation,
8
but seemingly being phased out of discussion in preference for the term
'promise'
3
and not always mentioned in popular introductions to the topic.
9
However, at least one library uses the term generically for abstracting
synchronicity and error handling, while not providing then functionality.
10
It's unclear if avoiding the term 'promise' was intentional, but probably a
good choice since promises are built around 'thenables.'
2
References
Wikipedia on Promises & Futures
Promises/A+ spec
DOM Standard on Promises
DOM Standard Promises Spec WIP
DOJO Toolkit Deferreds
jQuery Deferreds
Q
FutureJS
Functional Javascript section on Promises
Futures in AngularJS Integration Testing
Misc potentially confusing things
Difference between Promises/A and Promises/A+
(TL;DR, Promises/A+ mostly resolves ambiguities in Promises/A)
In light of apparent dislike for how I've attempted to answer the OP's question. The literal answer is, a promise is something shared w/ other objects, while a deferred should be kept private. Primarily, a deferred (which generally extends Promise) can resolve itself, while a promise might not be able to do so.
If you're interested in the minutiae, then examine Promises/A+.
So far as I'm aware, the overarching purpose is to improve clarity and loosen coupling through a standardized interface. See suggested reading from #jfriend00:
Rather than directly passing callbacks to functions, something which
can lead to tightly coupled interfaces, using promises allows one to
separate concerns for code that is synchronous or asynchronous.
Personally, I've found deferred especially useful when dealing with e.g. templates that are populated by asynchronous requests, loading scripts that have networks of dependencies, and providing user feedback to form data in a non-blocking manner.
Indeed, compare the pure callback form of doing something after loading CodeMirror in JS mode asynchronously (apologies, I've not used jQuery in a while):
/* assume getScript has signature like: function (path, callback, context)
and listens to onload && onreadystatechange */
$(function () {
getScript('path/to/CodeMirror', getJSMode);
// onreadystate is not reliable for callback args.
function getJSMode() {
getScript('path/to/CodeMirror/mode/javascript/javascript.js',
ourAwesomeScript);
};
function ourAwesomeScript() {
console.log("CodeMirror is awesome, but I'm too impatient.");
};
});
To the promises formulated version (again, apologies, I'm not up to date on jQuery):
/* Assume getScript returns a promise object */
$(function () {
$.when(
getScript('path/to/CodeMirror'),
getScript('path/to/CodeMirror/mode/javascript/javascript.js')
).then(function () {
console.log("CodeMirror is awesome, but I'm too impatient.");
});
});
Apologies for the semi-pseudo code, but I hope it makes the core idea somewhat clear. Basically, by returning a standardized promise, you can pass the promise around, thus allowing for more clear grouping.
What really made it all click for me was this presentation by Domenic Denicola.
In a github gist, he gave the description I like most, it's very concise:
The point of promises is to give us back functional composition and error bubbling in the async world.
In other word, promises are a way that lets us write asynchronous code that is almost as easy to write as if it was synchronous.
Consider this example, with promises:
getTweetsFor("domenic") // promise-returning async function
.then(function (tweets) {
var shortUrls = parseTweetsForUrls(tweets);
var mostRecentShortUrl = shortUrls[0];
return expandUrlUsingTwitterApi(mostRecentShortUrl); // promise-returning async function
})
.then(doHttpRequest) // promise-returning async function
.then(
function (responseBody) {
console.log("Most recent link text:", responseBody);
},
function (error) {
console.error("Error with the twitterverse:", error);
}
);
It works as if you were writing this synchronous code:
try {
var tweets = getTweetsFor("domenic"); // blocking
var shortUrls = parseTweetsForUrls(tweets);
var mostRecentShortUrl = shortUrls[0];
var responseBody = doHttpRequest(expandUrlUsingTwitterApi(mostRecentShortUrl)); // blocking x 2
console.log("Most recent link text:", responseBody);
} catch (error) {
console.error("Error with the twitterverse: ", error);
}
(If this still sounds complicated, watch that presentation!)
Regarding Deferred, it's a way to .resolve() or .reject() promises. In the Promises/B spec, it is called .defer(). In jQuery, it's $.Deferred().
Please note that, as far as I know, the Promise implementation in jQuery is broken (see that gist), at least as of jQuery 1.8.2.
It supposedly implements Promises/A thenables, but you don't get the correct error handling you should, in the sense that the whole "async try/catch" functionality won't work.
Which is a pity, because having a "try/catch" with async code is utterly cool.
If you are going to use Promises (you should try them out with your own code!), use Kris Kowal's Q. The jQuery version is just some callback aggregator for writing cleaner jQuery code, but misses the point.
Regarding Future, I have no idea, I haven't seen that in any API.
Edit: Domenic Denicola's youtube talk on Promises from #Farm's comment below.
A quote from Michael Jackson (yes, Michael Jackson) from the video:
I want you to burn this phrase in your mind:
A promise is an asynchronous value.
This is an excellent description: a promise is like a variable from the future - a first-class reference to something that, at some point, will exist (or happen).
A Promise represents a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers to an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of the final value, the asynchronous method returns a promise of having a value at some point in the future.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
The deferred.promise() method allows an asynchronous function to prevent other code from interfering with the progress or status of its internal request. The Promise exposes only the Deferred methods needed to attach additional handlers or determine the state (then, done, fail, always, pipe, progress, state and promise), but not ones that change the state (resolve, reject, notify, resolveWith, rejectWith, and notifyWith).
If target is provided, deferred.promise() will attach the methods onto it and then return this object rather than create a new one. This can be useful to attach the Promise behavior to an object that already exists.
If you are creating a Deferred, keep a reference to the Deferred so that it can be resolved or rejected at some point. Return only the Promise object via deferred.promise() so other code can register callbacks or inspect the current state.
Simply we can say that a Promise represents a value that is not yet known where as a Deferred represents work that is not yet finished.
A promise represents a value that is not yet known
A deferred represents work that is not yet finished
A promise is a placeholder for a result which is initially unknown while a deferred represents the computation that results in the value.
Reference
http://blog.mediumequalsmessage.com/promise-deferred-objects-in-javascript-pt1-theory-and-semantics

JavaScript Promises and race conditions

I just started using Promises in JavaScript using the Q library. I am running into a race condition and am wondering what would be the best way to resolve it.
The problem is that Q always calls the callbacks using process.nextTick() (also mentioned in the Promises/A+ spec) which means that I might miss some state changes in the object in the time between the resolution of the promise and the time the callbacks are called. My concrete problem is that I have an incoming connection and am missing the first messages. Messages are distributed using EventEmitter.
The code looks something like this. It uses the palava-client (but the problem should be universal) and is written in CoffeeScript:
defer = q.defer()
session.on 'peer_joined', (peer) ->
defer.resolve(peer)
return defer.promise
And somewhere else
peer_promise.then (peer) ->
peer.on 'message', (msg) ->
console.log "Message received:", msg
The first messages sometimes are lost because they got emitted before the promise ever got notified. The problem does not occur using only EventEmitter and Callbacks because the callbacks are always called immediately blocking the JavaScript Thread from handling the incoming messages.
The following code never misses messages:
session.on 'peer_joined', (peer) ->
peer.on 'message', (msg) ->
console.log "Message received:", msg
Do you see any way I can solve the problem using promises? I really would like to keep using them in my abstraction layer to ensure that only one peer is accepted. Is there any other way to avoid such race conditions?
As someone who usually promotes using promises, my suggestion is:
Do not use promises here
Promises represent one time events. They are an abstraction over values, one a promise changes its state it can no longer be changed. A promise starts off as pending and changes state once to either fulfilled or rejected.
You are facing a scenario where you have many users, each user joins and needs to add events, the users might 'go away', your scenario simply doesn't describe the same linear flow promises excel at. Promises are useful for a certain scenario - they are not for every concurrency problem. Using an event-emitter here is perfectly appropriate.
Your case (a user joining) does not really represent a resolved proxy operation. The code that "doesn't miss messages" is indeed more correct.
If you still choose to use promises here
There are a few things you can do:
You can use Q's progression events and add a progress handler in the creation phase. Note that Kris (Q's author) has called progression broken, and it is being removed in the next version of Q. I recommend against it.
You can wrap the message callback to only fire once a handler has been attached - accumulate items fired with a handler when it is created (in an array) and then trigger them all when the message handler is added (after you resolve, in a .then on the deferred you return.

Why are Q.js promises asynchronous after they have been resolved?

If I have the following :
var deferred = Q.defer();
deferred.resolve();
var a = deferred.promise.then(function() {
console.log(1);
});
console.log(2);
...why do I see 2, then 1 in the console?
I understand this output is correct according to the Promises spec, which says to call the function on the next tick (e.g. setTimeout()), even if it is already resolved, but I don't understand why.
I would like to have code that calls then on a series of promises synchronously, assuming that all the promises have been resolved.
My real use case is that I am trying to use Angular's implementation, $q, and I want all of the then callbacks to execute in the same $digest cycle, so that I don't get unnecessary subsequent $digest cycles.
Answer is consistency.
In real code, you don't have promises that are always immediately resolved when created, they would be pointless. So you have promises that sometimes may be immediately resolved.
In that case, you don't want to have a different flow. You want always the same, predictable flow. So you want the next function to be always called on next tick.
Don't use a promise when you don't need one.
It's a design mistake based on a set of opinions and assumptions. It has become latched because it was rushed out without full technical verification in a design by committee process that also had the back pressure of a lot of vendors implementing their own already with the same mistake making it hard to backtrack.
Once a standard goes out for JS to the web it can be revoked, even if it's broken with the idea being that webpages shouldn't break. If someone wrote a page today, then died, it should be possible to still view it in your browser in five years. It would be very problematic if when browsing the web you kept bumping into pages that didn't work with your browser.
In very simple use cases it doesn't do much harm and removes confusion about whether something is maybe async.
For increasingly non-trivial use cases it causes increasingly more harm and adds confusion. Initially it appears to make it easier to reason about your code but it sacrifices the less trivial usage for the least trivial usage.
It's overall much easier to reason about your code if it doesn't run things in the next tick that don't need to be async at all. This is a case of choosing to damage the language at level two to cater to level one users, at the expense of level two users and above, rather than working to help ascend level one users to level two users. It's a condescending or pessimistic design decision.
There's an intermediate solution where it's possible to run each task as if it runs after the current code runs to completion but things are scheduled in the correct order. This hasn't been implemented and it's also debatable as compromises don't always produce the best solutions. This compromise produces performance issues for direct return callstacks.
The way promises work means that the forward callstack is depth first and run to completion (isolated) but the return callstack is breadth first and run in pieces interleaved with other return callstacks. These are two radically different concept and behaviours. Traditionally with callbacks both run in the same way.
It also means you can't naively replace callbacks with promises or anything based on promises. Callbacks give you more options which promises take away. If you replace callbacks with promises without taking this difference into account you can create code that has stability issues and potential security issues as well since this behaviour of unordering events can cause the current code flow to unexpectedly jump track.
You can't rely on order which means there are cases with promises where if you ask for lots of things when you get them back you have to double check they're the thing you asked for where as you would not need to do this with callbacks. You may also need to buffer and reorder events which you would not need to do with callbacks. It can make benchmarks unreliable as well if you're not careful to isolate the two things being run.
This can also create serious performance bottlenecks that you can't always easily prevent. If you use promises a hundred returned results returned at once from a single event to an iterator, each taking one second per return call and their promise resolve depth is two, they'll all be broken into half with the first halves all run then the second halves. That means it will take 50.5 seconds before anything can finish where as with callbacks after 50 seconds half of them would already be finished. If the result of the task is passed along to another external service for processing then it leaves that service standing idle for 50 seconds when it could have been processing your results. This makes the promises terrible for when you want both low latency and high throughput under services that take load demonstrating the weakness of the design.
Not being able to naively replace callbacks with promises is one of the most devastating consequences of this design mistake which is also carried over to async/await. If you want to convert a callback library you can't simple change the syntax, you must carefully scrutinise the semantics at every point.
There is no plan to fix this. You can create your own promises and generators can be used to provide the same kind of syntax as async/await but with the same predictable and high performance behaviour of callbacks. You may however have problems playing nice with other libraries that still rely on native promises.

Categories

Resources