Reputation: 3015
How do I use defer correctly? I've got two functions here, in which one defer is used correctly? In which one it is used incorrectly? And why resp. why not?
First example:
getFoo1: function() {
var dfd = $q.defer();
db.allDocs({include_docs: true}, function(err, response) {
if(err) {
console.log(err);
dfd.reject(err);
} else {
var qcs = [];
for(var i=0; i < response.total_rows; i++) {
if(response.rows[i].doc.type == 'bar') {
var qc = {id: response.rows[i].doc._id,
isFoo: true
};
oneFunction(qc)
.then(anotherFunction(qc))
.then(qcs.push(qc));
}
}
dfd.resolve(qcs);
}
});
return dfd.promise;
},
Second example:
getFoo2: function() {
var dfd = $q.defer();
db.allDocs({include_docs: true}, function(err, response) {
if(err) {
dfd.reject(err);
} else {
dfd.resolve(response);
}
});
return dfd.promise
.then(function(response) {
var foo = [];
for(var i=0; i < response.total_rows; i++) {
if(response.rows[i].doc.type == 'bar') {
var qc = {id: response.rows[i].doc._id,
isFoo: true
};
return oneFunction(qc)
.then(anotherFunction(qc))
.then(foo.push(qc));
}
}
}, function(err){
console.log(err);
});
},
The oneFunction
does nothing asynchronously.
The anotherFunction
does something asynchronously (retrieving data from an external database).
EDIT: Thanks to @Bergi the correct function should look like this:
getFoo3: function() {
var dfd = $q.defer();
db.allDocs({include_docs: true}, function(err, response) {
if(err) {
dfd.reject(err);
} else {
dfd.resolve(response);
}
});
return dfd.promise
.then(function(response) {
var foos = [];
for (var i=0; i < response.total_rows; i++) {
if (response.rows[i].doc.type == 'bar') {
var qc = {id: response.rows[i].doc._id,
isFoo: true
};
var foo = oneFunction(qc);
foos.push(foo);
}
}
var promises = foos.map(anotherFunction); // make a promise for each foo
return $q.all(promises);
}, function(err){
console.log(err);
});
},
Upvotes: 1
Views: 136
Reputation: 664405
You've used $q.defer
correctly in the second example[1] - creating a promise for the response of the db.allDocs
asynchronous call (and nothing else). Altough pochdb seems to already return promises, as @Benjamin mentions in the comments, so it's unnecessary (but not wrong).
The first example is just a mess, convoluting the construction of the promise with the error logging and that ominous loop.
1: Except for dfd.promise()
, which is not a function but a property. Go for dfd.promise.then(…)
.
However, that loop is a very different topic, and seems to be wrong in both snippets. Some points:
return
from the callback function in the body of the loop, right on the first iteration that fulfills the predicate.oneFunction(qc)
is not asynchronous, it doesn't need to (read: shouldn't) return a promise - or if it does not, that .then(…)
call is wrong.anotherFunction(qc)
seems to return a promise (it's asynchronous as you say). But you must not pass that promise to .then()
, a callback function is expected there!foo.push(qc)
- it's not a callback function that you would pass to .then()
.Promise.all
now!If I had to bet, I'd say you need
.then(function(response) {
var foos = [];
for (var i=0; i < response.total_rows; i++) {
if (response.rows[i].doc.type == 'bar') {
var qc = {id: response.rows[i].doc._id,
isFoo: true
};
var foo = oneFunction(qc);
foos.push(foo);
}
}
var promises = foos.map(anotherFunction); // make a promise for each foo
return $q.all(promises);
})
Upvotes: 2