Reputation: 12646
I have read every article on $q out there but somehow I am unable to grasp it. For example take the best article I found. I get as far as:
var myFirstDeferred = $q.defer(); //Actually I don't even get this far
A deferred represents the result of an asynchronic operation. It exposes an interface that can be used for signaling the state and the result of the operation it represents. It also provides a way to get the associated promise instance.
What's a 'deferred'? How is it different from a promise? Then we get to this:
async(function(value) {
myFirstDeferred.resolve(value);
}, function(errorReason) {
myFirstDeferred.reject(errorReason);
});
I have NO idea what this is doing. I want to stress that I understand async. I understand the promise structure. For example I know exactly what the code below is doing:
$http.get(url)
.then(function(result){returnresult}
,function(error){return error})
But what are we doing with the deferred in the object above? Why even have the deferred at all? Why not just the then block?
Edit: I want to stress that I went through a ton of replies here, as well as the articles. I thought the point of $q was the force the execution of an async call (kind of like "await" in c#) and then perform some code after. I really don't understand how it does that. I do get how the .all command works when waiting for multiple async operations in this example, but not with one.
Edit: This edit is in response to the duplicate suggestion - I disagree with the notion. For one, this question is more focused and limited in scope. In addition, the answer accepted here clarifies far better (imo) than the wide-net answer in the other q.
Upvotes: 1
Views: 1855
Reputation: 191749
Typically you don't have to use a deferred explicitly. If you find yourself using $q.defer
you should question why you are not using the promise interface directly. See the bluebird
documentation for a description of why. $http
and many other libraries use deferreds internally and return promises from the methods they expose so using deferreds on top of this is unnecessary.
That being said, deferreds can be useful and understanding them is important. Typically, deferreds have two methods: .reject
and .resolve
. Honestly there could be one method that you could use to mark the result of an asynchronous operation:
.reject -> the asynchronous operation failed or could not complete
.resolve -> the asynchronous operation completed successfully
When a deferred is completed, it triggers the promise callbacks.
You need to use $q.defer
or deferreds when dealing with operations that are asynchronous but do not have a built in promise interface such as timers:
var dfd = $q.defer();
$timeout(function () {
// this is asynchronous
// it completed successfully
dfd.resolve("some value");
}, 500);
dfd.promise.then(function (value) {
assert.equal(value, "some value");
});
Rather than using deferreds as an object interface, Angular allows you to use these destructured as function arguments to $q
Rewriting the above:
var promise = $q(function (resolve) {
$timeout(function () {
resolve("some value");
}, 500);
});
promise.then(function (value) {
assert.equal(value, "some value");
});
Upvotes: 2
Reputation: 32076
A deferred object is just a subset of a promise that only gives you .reject and .resolve, which prevents the outside world from doing anyting else with it. If you can't return a promise (like when using a library built on callbacks, not promises), make a deferred and manually reject or resolve it.
deferred.reject
and deferred.resolve
only matter when you return the deferred. Basically:
somePromise().then( function() {
var deferred = q.defered();
someFunctionThatHasCallback( function() {
deferred.resolve();
});
return defererd;
}).then( function() {
console.log( 'I wait for deferred.resolve' );
});
If your functions return promises, you don't need deferred, because promises are chainable by returning inside .then
somePromise().then( function() {
return someFunctionThatReturnsPromise();
}).then( function() {
console.log( 'I wait for promise to resolve' );
});
Upvotes: 1