I've been reading a lot about React for the last 3 days, but I don't see much information about the use of promises, so I have that concern.
Is there any library for this?
How should I use promises in React?
React doesn't come with a promise library baked in like Angular with $http. You will have to find your own.
A few you can try:
Bluebird (personal recommendation)
jQuery's $ajax
Native promises (unless you actually have to support IE): http://caniuse.com/#feat=promises
Promise object is used for handling asynchronous computations which has some important guarantees that are difficult to handle with the callback method (the more old-school method of handling asynchronous code).
A Promise object is simply a wrapper around a value that may or may not be known when the object is instantiated and provides a method for handling the value after it is known (also known as resolved) or is unavailable for a failure reason (we'll refer to this as rejected).
Using a Promise object gives us the opportunity to associate functionality for an asynchronous operation's eventual success or failure (for whatever reason). It also allows us to treat these complex scenarios by using synchronous.
To see more at : https://www.npmjs.com/package/react-promise
Related
I'm wondering if custom "thenables" (aka an object with a .then() method) are approved/documented? How do they compare to real Promises? I suppose it matters how you implement then, so I'm wondering if there's documentation with some DOs and DONTs.
This page suggests:
.then may return an arbitrary “thenable” object, and it will be treated the same way as a promise.
Can't find any docs on this.
How do thenables compare to real Promises?
In that you don't know whether they are real promises or not. Have a look at Regarding Promises/A+ Specification, what is the difference between the terms "thenable" and "promise"?.
I'm wondering if there's documentation with some DOs and DONTs about how to implement them (as that seems to be what matters)
There's the (pretty simple) Promises/A+ specification that documents how thenables are treated. ES6 promises (and by extension, await) follow this. Basically:
your object has a property with the name then whose value is a function
the function will get called with two callbacks
you can call either of them - asynchronously or not
the first call determines what happens to the promise that assimilated your thenable
It's really no magic. You call the first argument when you want to resolve with a value, and you call the second argument when you want to reject. There are no DONTs assuming a proper promise implementation - you can call the callbacks as often as you want, and keep them around as long as you want: the calls should be ignored and the reference should not leak memory.
According to Promise - Javascript | MDN,
The constructor is primarily used to wrap functions that do not
already support promises.
At a low level, the functions that already support promises would
be doing this right i.e constructing a promise using Promise and returning it back?
Is there a better way to create a promise other than using the Promise constructor function?
Eventually, you have to register a callback somewhere right? I mean you can't avoid having a callback that at-least resolves? In other words, we have to wrap it like this somewhere in the library correct?
At the lowest level? Yes, probably.
Depends on the context. If the value you want to resolve the value to is already available, then you'd use Promise.resolve(theValue). If you want to wait for multiple promises you'd use Promise.all(allThePromises). And of course every call to .then returns a new promise.
If you want to do anything with the value of a promise, then yes, you have to pass a callback to .then. There is no other way to get the value.
Having said all that, ES2017 introduced async functions which are basically syntactic sugar for promises. async functions always return a promise and you can use await to unwrap promises. Example:
async function get() {
return await Promise.resolve(42);
}
get().then(console.log);
At a low level, the functions that already support promises would be doing this right i.e constructing a promise using Promise and returning it back?
The eventual goal is that even the low-level APIs within Node.JS will be using the Promise syntax so there will be no need for callbacks. The PromiseJS community considers the constructor syntax to be a polyfill for this eventual behavior. Source.
In practice, this is obviously not the case. Browsers, Node.JS and other Javascript runtime environments make heavy use of callbacks, and so the Promise constructor is used.
Is there a better way to create a promise other than using the Promise constructor function?
Yes- but this depends on application.
Most obviously, if you are using an API which already returns a promise, you can use .then() and .catch() syntax to chain promises together.
There are also a number of libraries which extend the default Promise functionality and provide convenience methods for increased performance and readability. For instance, Bluebird (a common PromiseJS library) offers a way to evaluate the result of multiple promises created concurrently for faster overall runtime.
You can also construct Promises from other paradigms which simplify code- for instance Promise.Promisify which converts a callback function into a Promise one, or Observable.toPromise which converts Observables to promises.
Eventually, you have to register a callback somewhere right? I mean you can't avoid having a callback that at-least resolves? In other words, we have to wrap it like this somewhere in the library correct?
Similar to the answer to your first question, this is a symptom of code currently using the callback paradigm. If all libraries used Promises on a lower level, this wouldn't be the case.
At a low level, the functions that already support promises would be doing this right i.e constructing a promise using Promise and returning it back?
Yes. Maybe. At a low level, we don't know how functions that already support promises do construct those. Imagine what the Promise constructor itself uses to construct promises…
Is there a better way to create a promise other than using the Promise constructor function?
No, there's no other way accessible to JS. But as MDN notes, you should rarely ever need to do this yourself, and rather just use other functions that already create promises for you (which by themselves of course go through the Promise constructor somehow).
Eventually, you have to register a callback somewhere right? I mean you can't avoid having a callback that at-least resolves?
Not necessarily. At a low level, you could also register any arbitrary data structure that allows to resolve a promise, this does not necessarily need to be a callback function. (It is however indeed equivalent in power to registering the resolve callback function).
For example the native implementation of the fetch API (afaik the first native API that directly returns promises) will hardly create JS callback functions anywhere to resolve its promises.
I have seen different ways of doing multiple dependent ajax synchronous call. Two of which is being widely adopted is the jquery defer method and callback on success.
My question is:
1) What is the advantage of using one over another?
2) In what situation is one is preferred over another?
3) Is there any other better method than these 2?
// jquery defer method
var defer = $.when(
$.get('ajax_call_1');
);
defer.done(function () {
$.get('ajax_call_2');
});
// callback on success
$(function(){
$.ajax({
url:'/ajax_call_1',
data: { },
success: function(data){
$.get('ajax_call_2');
}
});
}
});
Some reasons to use Promises over Callbacks:
Much simpler to sequence multiple asynchronous operations.
Much simpler to build conditional logic involving multiple asynchronous operations.
Much simpler to do robust error handling involving multiple asynchronous operations.
Much simpler to build reusable asynchronous interfaces.
Much simpler to interface with other asynchronous interfaces.
Much simpler to deal with exceptions that might occur deep in asynchronous code that would otherwise cause silent failure
In your question, the simplest way to sequence jQuery Ajax calls and catch all possible errors is to use the natural promises returned from $.ajax() and chain them:
$.get('ajax_call_1').then(function(value) {
return $.get('ajax_call_2');
}).then(function(result) {
// success with both here
}, function(err) {
// error with one of them here
});
Or, with no error handling like in your example:
$.get('ajax_call_1').then(function(value) {
$.get('ajax_call_2');
})
There is no reason to use this construct here:
// jquery defer method
var defer = $.when(
$.get('ajax_call_1');
);
because $.get() already returns a promise so there is no need to use $.when() to just create yet another promise. $.when() is useful when you have more than one promise and you want to know when all of them are done. For one promise, you just use it directly - no reason to use $.when() with a single promise.
You can do it your second way:
// callback on success
$.ajax({
url:'/ajax_call_1',
data: { },
success: function(data){
$.get('ajax_call_2');
}
});
As this is just the non-promise way of coding with nested callbacks. The major disadvantage is that propagation of errors and sequencing multiple operations gets messy and difficult when not using promises. In just this simple example, try to get the error from either of the ajax calls back to the caller. It takes a lot of extra code to do that. My promise example above propagates all errors back to the caller for you.
As for your specific questions:
1) What is the advantage of using one over another?
You're basically asking why use promises over nested callbacks. There are hundreds of articles on the advantages of using promises. I will see if I can find one or two, but a Google search for "why promises vs. callbacks" should get you started on some reading.
What’s so great about JavaScript Promises?
Staying Sane with Asynchronous Programming
Why Am I Switching to Promises
2) In what situation is one is preferred over another?
I know of no reason why plain nested callbacks is preferred over using promises. Once you have learned promises, you will pretty much always find them a better way to code. The only reason I would not use promises is if I was trying to make code that was compatible with old browsers that did not have promises and even then, I'd probably just include a polyfill so that promises were supported.
3) Is there any other better method than these 2?
Yes, see my first code example.
P.S. Note that I choose to only use .then() with jQuery promises because that is the ES6 promise standard and it will make it easier in the future when jQuery transitions its promises to be more standards-compatible (which they are working on). Your code will also be more consistent when interfacing with other sources of promises that do use the standard.
P.P.S. Promises are one-shot devices. They either resolve or reject once and only once. If you are trying to get multiple notifications from some source, then promises are not built for that. An event emitter or a publish/subscribe system might be a better match for that type of problem.
It seems generally that creating deferred objects is now commonly discouraged in favor of using the ES6-style Promise constructor. Does there exist a situation where it would be necessary (or just better somehow) to use a deferred?
For example, on this page, the following example is given as justification for using a deferred:
function delay(ms) {
var deferred = Promise.pending();
setTimeout(function(){
deferred.resolve();
}, ms);
return deferred.promise;
}
However, this could be done just as well with the Promise constructor:
function delay(ms) {
return new Promise(function(resolve, reject){
setTimeout(function(){
resolve();
}, ms);
});
}
Does there exist a situation where it would be necessary (or just
better somehow) to use a deferred?
There is no such situation where a deferred is necessary. "Better" is a matter of opinion so I won't address that here.
There's a reason that the ES6 promise specification does not have a deferred object. You simply don't need one. Anything that people used to use a deferred object for can always be done another way that doesn't use a deferred object.
First off, the majority of uses fit very nicely into the promise constructor model. Secondly, any other cases that didn't fit quite so cleanly into that model can still be accomplished with the promise constructor or by starting with a resolved promise and chaining to it.
The main use case I've seen for a deferred is when you want to pass the ability to resolve() or reject() off to some other piece of code other than the code that created the promise. A Deferred made that very easy since you could just pass the deferred object and it had public methods for resolving or rejecting it. But, with a promise, you can also just pass the resolve and/or reject methods. Since they are bound to the specific object automatically, you can just pass the function references. And, in other cases, you can just let the other code create their own promise and resolve/reject it themselves and have that operation linked to yours rather than letting them resolve/reject your promise. Is all that quite as clean as passing a deferred object? Mostly a matter of opinion, but neither are very common use cases and all are something that can be accomplished without a separate deferred object.
And, as torazaburo points out, letting some external code resolve or reject your promise is a bit of an anti-pattern in its own right. You created the promise - you resolve/reject it. If you want to use external events to decide when to resolve/reject it, then have them notify you (via their own promise or callback) and you can resolve/reject your own promise. Or, have them create their own promise that you can use. That's really the desired model. Or, let them chain onto your promise so that the end result is gated by when their operation is done.
If one was used to coding with the deferred object (say with a jQuery deferred), it might take a little getting used to coding without it, but after a little while you just start to think differently and it starts to come natural to just use the promise constructor.
Once you promisify the sphere of async operations that you use in any given application, it's pretty rare that you ever even need to create your own promises any more because you are mostly just building off promises that the async functions you call are already creating or using flow control operations like Promise.all() which create uber promises for you.
This is the main point of anti-patterns. Use the promises that are already created for you rather than manually create more. Chain them. Return promises from .then() handlers to link async operations under logic control.
Of course, there are existing async operations that don't return promises for which somebody needs to create a promise, but that should be done in a promisify layer somewhere outside the purvey of your main coding logic and done only once for that operation and then code that calls the async operation should be able to just use the returned promises.
Native Promises don't have all the built-in methods that deferred has out of the box, for example the method to resolve the promise outside the scope of its constructor (very easy to implement with native Promise, though), and the ability to look at the status of a promise (which is hidden from regular JavaScript on native Promises, though it can be inspected in the dev tools).
The main reason to use deferred today would be backwards compatibility with code that depends on those extra methods. Hard to give a definitive answer to your question without stepping onto opinion territory.
Similar to the promises pattern I'm looking for an event pattern that avoids needing to pollute objects with addEventListener/etc methods, I want to be able to return an object, that can be cancelled as well as 'resolved' multiple times.
For example, I may write a method that returns an 'interval' object, something like this:
var ticker = createTicker(1000);
var subscription = ticker.then(function() { console.log('tick') });
... later on ...
subscription.cancel();
The key differences here being, similar to a promise the events are standardized, so that I can subscribe without needing to know the event name, however unlike a promise, the "completion" can happen multiple times, and may even be cancelled (this would be equiv of removeEventListener).
I'm interested to see if this is legal with promises, such that the progress handler could be used for multiple callbacks, and the complete handler never used, but more importantly, that there is a concept of unsubscribing from a promise.
If this isn't the case, and promises are specialized to this scenario, is there a standardized pattern for doing what I described?
The ability to cancel can be added to a promise implementation, without breaking the main paradigm of having single-fire success/failure callbacks.
In fact, jQuery already has cancellation for the promise instances that it returns from jQuery.ajax calls:
For backward compatibility with XMLHttpRequest, a jqXHR object will
expose the following properties and methods:
readyState
status
statusText
responseXML and/or responseText when the underlying request responded with xml and/or text, respectively
setRequestHeader(name, value) which departs from the standard by replacing the old value with the new one rather than concatenating the new value to the old one
getAllResponseHeaders()
getResponseHeader()
abort()
You could write a setTimeout wrapper that exposes a promise interface along with an additional cancel method.
However, once you get into the multi-fire territory, I think that is not what promises are intended for. You would have to define a lot of rules and exceptions around how multiple firing will play out alongside regular promise functionality. It doesn't make a lot of sense to me to use promises that way.
Update (based on discussion in comments):
Here's a sample implementation of a promise "proxy" that allows aborting further relaying of the done/fail callbacks:
http://jsfiddle.net/atesgoral/qvtqu/