Difference Between Defer().Promise and Promise

Difference between defer().promise and Promise

Well, this is about the promise resolution source. Q and a bunch of other libraries offer two APIs:

  • The legacy defer API - in which you create a deferred that you can .resolve(value) and it has a promise you can return.
  • The promise constructor - which is the modern API in which you create the promise from a completion source.

Roughly doing:

var d = Q.defer();
setTimeout(function(){ d.resolve(); }, 1000);
return d.promise;

Is the same as:

return new Promise(function(resolve, reject){
setTimeout(resolve, 1000);
});

so you might be asking

Why do we need two APIs?

Well, the defer API came first. It's how some other languages deal with it, it's how the papers deal with it and it's how people used it first - however - there is an important difference between the two APIs. The promise constructor is throw safe.

Throw safety

Promises abstract exception handling and are throw safe. If you throw inside a promise chain it will convert that exception into a rejection, quoting the spec:

If either onFulfilled or onRejected throws an exception e, promise2 must be rejected with e as the reason

Let's assume you're parsing JSON from an XHR request:

function get(){
var d = Q.defer();
if(cached) { // use cached version user edited in localStorage
d.resolve(JSON.parse(cached));
} else { // get from server
myCallbackApi('/foo', function(res){ d.resolve(res); });
}
}

Now, let's look at the promise constructor version:

function get(){
return new Promise(function(resolve, reject){
if(cached) { // use cached version user edited in localStorage
resolve(JSON.parse(cached));
} else { // get from server
myCallbackApi('/foo', resolve);
}
});
}

Now, assume somehow your server sent you invalid JSON (or the user edited it to an invalid state) and you cached it.

In the defer version - it throws synchronously. So you have to generally guard against it. In the bottom version it does not. The top version usage would look like:

try{
return get().catch(function(e){
return handleException(e); // can also just pass as function
});
} catch(e){
handleException(e);
}

In the bottom version - the promise constructor will convert throws to rejections so it is enough to do:

return get().then(function(e){
return handleException(e);
});

Preventing a whole class of programmer errors from ever happening.

Difference between promise and deferred when wrapping your entire block of code in a promise?

A deferred is an object that has the resolve and reject method, allowing it's state to be changed. A promise doesn't.

As for generating promises in both ways, generally there shouldn't be any difference. I prefer the syntax of Promises since it wraps your logic in a function and avoids polluting the outer scope with variables, but that's about it.

What are the differences between Deferred, Promise and Future in JavaScript?

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 is the difference between defer object promise and promise from $resource service

The promise returned from $resource is one someone initially used $q.defer() (or the newer more modern promise constructor) to create.

That someone is the $http service used internally inside $resource - you are using a promise they created for you.

Typically, you only need to use a $q.defer or the promise constructor at the lowest level of your code when working with async - otherwise you're typically better off using promise chaining. Otherwise you end up with the explicit construction anti-pattern.

Deferred versus promise

First: You cannot use $.Promise(); because it does not exist.

A deferred object is an object that can create a promise and change its state to resolved or rejected. Deferreds are typically used if you write your own function and want to provide a promise to the calling code. You are the producer of the value.

A promise is, as the name says, a promise about future value. You can attach callbacks to it to get that value. The promise was "given" to you and you are the receiver of the future value.

You cannot modify the state of the promise. Only the code that created the promise can change its state.

Examples:

1. (produce) You use deferred objects when you want to provide promise-support for your own functions. You compute a value and want to control when the promise is resolved.

function callMe() {
var d = new $.Deferred();
setTimeout(function() {
d.resolve('some_value_compute_asynchronously');
}, 1000);
return d.promise();
}

callMe().done(function(value) {
alert(value);
});

2. (forward) If you are calling a function which itself returns a promise, then you don't have to create your own deferred object. You can just return that promise. In this case, the function does not create value, but forwards it (kind of):

function fetchData() {
// do some configuration here and pass to `$.ajax`
return $.ajax({...});
}

fetchData().done(function(response) {
// ...
});

3. (receive) Sometimes you don't want to create or pass along promises/values, you want to use them directly, i.e. you are the receiver of some information:

$('#my_element').fadeOut().promise().done(function() {
// called when animation is finished
});

Of course, all these use cases can be mixed as well. Your function can be the receiver of value (from an Ajax call for example) and compute (produce) a different value based on that.


Related questions:

  • What are the differences between Deferred, Promise and Future in JavaScript?
  • What's the difference between a Deferred object and its own promise object?

What's the difference between a Deferred object and its own promise object?

It creates a "sealed" copy of the deferred value, without the .resolve() and .reject() methods. From the documentation:

The deferred.promise() method allows an asynchronous function to prevent other code from interfering with the progress or status of its internal request.

It's used when it doesn't make sense for the value to be modified. For example, when jQuery makes an AJAX request it returns a promise object. Internally it .resolve()s a value for the original Deferred object, which the user observes with the promise.

What is the difference of returning a promise() or a deferred in jQuery?

So what's the difference of returning deferred.promise() or only return deferred ?

You want to return deferred.promise() so that the calling code can't call resolve or reject or other Deferred-specific methods. That's not something the caller should have access to. It should only be able to consume the promise, not affect its state.



Related Topics



Leave a reply



Submit